Asp.net 2.0 自定义控件开发[开发一个图表(WebChart)控件(柱状图示例)]

翻译|其它|编辑:郝浩|2007-10-24 10:18:37.000|阅读 2688 次

概述:

# 界面/图表报表/文档/IDE等千款热门软控件火热销售中 >>

(一). 概述

       本文主要演示一个比较简单的 WebChart 柱状实现,  可以一方面了解一个较完整的控件开发实例, 里面用到了复合样式及视图存储等内容.  另一方面了解一下WebChart的实现原理.  在Web开发中, 最终是用浏览器呈现各种图表,  图表控件呈现过程是 根据控件提供的属性接口接收到数据参数, 用最基本的Html元素<Table><tr><td>来呈现图表.  

(二). 运行效果

      1.  在浏览器中运行的柱状图

      2.  主要属性 ( 可以通过修改这些属性参数修改其 外观样式和文本显示格式等信息)           

       

      主要属性用法介绍:  

SimpleGaugeBar 控件重要属性介绍
FormatString
设置显示的文本格式, 如: “68 of 100”
Maximum
全值大小, 如上图中设置了 100.
Segments
每段值, 如上图中设置了 10. 这样根据Maximum的值控件就能够算出共有 100/10=10段(全值共有10个td呈现)
TextStyle
显示文本样式复合属性
Value
设置有效值, 如上图中设置了 68.
ForeColor

柱装有效值长度标志颜色(根据Value值决定其长度)

BackColor
柱装全值标志颜色
BorderColor
柱状边框颜色

(三). 代码

       代码比较简单,就两个文件; 主要代码,都包含了中文注释。在这里对代码不作多介绍。

       1. 主控件文件 SimpleGaugeBar.cs 代码

  1 namespace KingControls
  2 
{
  3     /// <summary>

  4     /// Author: [ ChengKing(ZhengJian) ] 
  5     ///
 Blog:   Http://blog.csdn.net/ChengKing
  6     ///
 本代码 参照 Asp.net 2.0高级编程 方案
  7     /// </summary>

  8     [DefaultProperty("Value")]
  9     [ToolboxData("<{0}:SimpleGaugeBar runat=server></{0}:SimpleGaugeBar>"
)]
 10     [PersistChildrenAttribute(false
)]
 11     public class
 SimpleGaugeBar : CompositeControl
 12 
    {
 13         //在绘制输出画面时,标志是哪个TD为分界点(从这个分界点改变表格的颜色绘制)

 14         private int _intDividerCell;
 15 

 16         private TextItemStyle _textStyle;
 17 

 18         public SimpleGaugeBar()            
 19 
        {
 20 
        }
 21 

 22         #region 属性
 23         /// <summary>
 24         /// 进度条值
 25         /// </summary>

 26         public float Value
 27 
        {
 28             get

 29             {
 30                 object o = ViewState["Value"
];
 31                 if (o == null
)
 32                     return 0
;
 33                 return float
.Parse(o.ToString());
 34 
            }
 35             set

 36             {
 37                 this.ViewState["Value"=
 value;
 38                 if (value >
 Maximum)
 39 
                {
 40                     this.ViewState["Value"=
 Maximum;
 41 
                }
 42 
            }
 43 
        }
 44 

 45         /// <summary>
 46         /// 全值
 47         /// </summary>

 48         public float Maximum
 49 
        {
 50             get

 51             {
 52                 object o = this.ViewState["Maximum"
];
 53                 if (o == null
)
 54 
                {
 55                     return 100
;
 56 
                }
 57                 return float
.Parse(o.ToString());
 58 
            }
 59             set

 60             {
 61                 this.ViewState["Maximum"=
 value;
 62 
            }
 63 
        }
 64 

 65         /// <summary>
 66         /// 表示进度条分几段
 67         /// </summary>

 68         public int Segments
 69 
        {
 70             get

 71             {
 72                 object o = this.ViewState["Segments"
];
 73                 if (o == null
)
 74 
                {
 75                     return 4
;
 76 
                }
 77                 return int
.Parse(o.ToString());
 78 
            }
 79             set

 80             {
 81                 this.ViewState["Segments"=
 value;
 82                 if (value < 1
)
 83 
                {
 84                     this.ViewState["Segments"= 1
;
 85 
                }
 86 
            }
 87 
        }
 88 

 89         /// <summary>
 90         /// 文本呈现格式
 91         /// </summary>

 92         public string FormatString
 93 
        {
 94             get

 95             {
 96                 object o = this.ViewState["FormatString"
];
 97                 if (o == null
)
 98 
                {
 99                     return "<b>{0}</b>/<b>{1}</b>"
;
100 
                }
101                 return (string
)o;
102 
            }
103             set

104             {
105                 this.ViewState["FormatString"=
 value;
106 
            }
107 
        }
108 

109         public bool GridLines
110 
        {
111             get

112             {
113                 object o = this.ViewState["GridLines"
];
114                 if (o == null
)
115 
                {
116                     return true
;
117 
                }
118                 return (bool
)o;
119 
            }
120             set

121             {
122                 this.ViewState["GridLines"=
 value;
123 
            }
124 
        }
125 

126         [PersistenceMode(PersistenceMode.EncodedInnerDefaultProperty)]
127 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
128         [NotifyParentProperty(true
)]        
129         public
 TextItemStyle TextStyle
130 
        {
131             get

132             {
133                 if (_textStyle == null
)
134 
                {
135                     _textStyle = new
 TextItemStyle();
136 
                }
137                 if
 (IsTrackingViewState)
138 
                {
139 
                    ((IStateManager)_textStyle).TrackViewState();
140 
                }
141                 return
 _textStyle;
142 
            }
143 
        }
144 

145         #endregion
146 
147         #region 方法
148 
149         protected override void Render(HtmlTextWriter writer)
150 
        {
151 
            PrepareControlForRendering();            
152             base
.Render(writer);
153 

154             //base.RenderContents(writer);
155             //
this.RenderContents(writer);
156             //this.Render(writer);

157             
158 
        }
159 

160         protected override void CreateChildControls()
161 
        {
162             //base.CreateChildControls();

163             this.Controls.Clear();
164 
            CreateControlHierarchy();
165 
            ClearChildViewState();
166 
        }
167 

168         /// <summary>
169         /// 在Web开发中,用Table/TR/TD来表示图形输出
170         /// </summary>

171         protected virtual void CreateControlHierarchy()
172 
        {
173             //最外层表格

174             Table outer = new Table();
175             TableRow outerRow = new
 TableRow();
176 
            outer.Rows.Add(outerRow);
177 

178             TableCell rulerCell = new TableCell();
179 
            outerRow.Cells.Add(rulerCell);
180 
            BuildGaugeBar(rulerCell);
181 

182             //根据条件增加文本显示单元格
183             TableCell textCell = new TableCell();
184             if (!
TextStyle.DisplayTextAtBottom)
185 
            {
186 
                outerRow.Cells.Add(textCell);
187 
                BuildLabel(textCell);
188 
            }
189 

190             this.Controls.Add(outer);
191 

192             if (!TextStyle.RenderInsideTable && TextStyle.DisplayTextAtBottom)
193 
            {
194                 BuildLabel(null
);
195 
            }
196 
        }
197 

198         /// <summary>
199         /// 用Label来呈现文本,如: { 8/10 }
200         /// </summary>

201         /// <param name="tc"></param>
202         void BuildLabel(TableCell tc)
203 
        {
204             float buf =
 GetValueToRepresent();
205             string msg =
 GetTextToRepresent();
206 

207             Label lbl = new Label();
208             if (tc is
 TableCell)
209 
            {
210 
                tc.Controls.Add(lbl);
211 
            }
212             else

213             {
214                 this
.Controls.Add(lbl);
215 
            }
216             lbl.Text =
 String.Format(msg, buf, Maximum);
217 
        }
218 

219         void BuildGaugeBar(TableCell tc)
220 
        {
221             Table t = new
 Table();
222             TableRow tr = new
 TableRow();
223 
            t.Rows.Add(tr);
224 

225             BuildRuler(tr);
226 

227             if (TextStyle.RenderInsideTable)
228 
            {
229 
                BuildLabelIntoTable(t);
230 
            }
231 
            tc.Controls.Add(t);
232 
        }
233 

234         void BuildRuler(TableRow ruler)
235 
        {
236             float val =
 GetValueToRepresent();
237             float valueToRepresent = 100f * val /
 Maximum;
238             int numOfSegments =
 GetNumOfSegments();
239             int segmentWidth = 100 /
 numOfSegments;
240             bool finished = false
;
241             for (int i = 1; i <= numOfSegments; i++
)
242 
            {
243                 if (valueToRepresent < i *
 segmentWidth)
244 
                {
245                     if
 (finished)
246 
                    {
247                         TableCell stillToDo = new
 TableCell();
248 
                        ruler.Cells.Add(stillToDo);
249                         stillToDo.Width =
 Unit.Percentage(segmentWidth);
250 
                    }
251                     else

252                     {
253                         _intDividerCell = i - 1
;
254                         TableCell cell = new
 TableCell();
255 
                        ruler.Cells.Add(cell);
256                         cell.Width =
 Unit.Percentage(segmentWidth);
257                         cell.Height = Unit.Percentage(100
);
258 

259                         //增加子表
260                         Table child = new Table();
261                         child.Width = Unit.Percentage(100
);
262                         child.Height = Unit.Percentage(100
);
263 
                        cell.Controls.Add(child);
264                         child.CellPadding = 0
;
265                         child.CellSpacing = 0
;
266                         TableRow childRow = new
 TableRow();
267 
                        child.Rows.Add(childRow);
268 

269                         float fx = (100 * (valueToRepresent - segmentWidth * (i - 1)) / segmentWidth);
270                         if (valueToRepresent > (i - 1*
 segmentWidth)
271 
                        {
272                             TableCell left = new
 TableCell();
273 
                            childRow.Cells.Add(left);
274                             left.Width =
 Unit.Percentage(fx);
275 
                        }
276                         TableCell right = new
 TableCell();
277 
                        childRow.Cells.Add(right);
278                         right.Width = Unit.Percentage(100 -
 fx);
279                         finished = true
;
280 
                    }
281 
                }
282                 else

283                 {
284                     TableCell done = new
 TableCell();
285 
                    ruler.Cells.Add(done);
286                     done.Width =
 Unit.Percentage(segmentWidth);
287 
                }
288 
            }
289 
        }
290 

291         /// <summary>
292         /// 创建最外Table的第二行, 显示文本
293         /// </summary>

294         /// <param name="t"></param>
295         void BuildLabelIntoTable(Table t)
296 
        {
297             float buf =
 GetValueToRepresent();
298             int numOfSegments =
 GetNumOfSegments();
299             string msg =
 GetTextToRepresent();
300             if
 (TextStyle.DisplayTextAtBottom)
301 
            {
302                 TableRow label = new
 TableRow();
303 
                t.Rows.Add(label);
304                 TableCell lblCell = new
 TableCell();
305 
                label.Cells.Add(lblCell);
306 

307                 lblCell.ColumnSpan = numOfSegments;
308                 lblCell.Text =
 String.Format(msg, buf, Maximum);
309 
            }
310 
        }
311 

312         private string GetTextToRepresent()
313 
        {
314             return this
.FormatString;
315 
        }
316 

317         private int GetNumOfSegments()
318 
        {
319             return this
.Segments;
320 
        }
321 

322         private float GetValueToRepresent()
323 
        {
324             return this
.Value;
325 
        }
326 

327         /// <summary>
328         /// 增加样式
329         /// </summary>

330         private void PrepareControlForRendering()
331 
        {
332             if (this.Controls.Count < 1
)
333 
            {
334                 return
;
335 
            }
336             Table outer = (Table)Controls[0
];            
337             outer.CellPadding = 0
;
338             outer.CellSpacing = 0
;
339             outer.Width = Unit.Percentage(100
);
340             outer.Height = Unit.Percentage(100); //this.Height;

341             outer.BorderWidth = Unit.Empty;
342 

343             Table t = (Table)outer.Rows[0].Cells[0].Controls[0];           
344 

345             t.CopyBaseAttributes(this);
346 

347             t.CellPadding = 0;
348             t.CellSpacing = 0
;
349             t.Width = Unit.Percentage(100
);
350             t.Height = Unit.Pixel(17
);
351             t.BorderWidth =
 Unit.Empty;
352 

353             for (int i = 0; i < Segments; i++ )
354 
            {
355                 TableCell cell = t.Rows[0
].Cells[i];
356                 if
 (GridLines)
357 
                {
358                     cell.BackColor = this
.BorderColor;
359                     cell.BorderStyle = this
.BorderStyle;
360                     cell.BorderWidth = this
.BorderWidth;                   
361 
                }
362 

363                 //为刻度前面的表格设置颜色
364                 if (i < _intDividerCell)
365 
                {
366                     cell.BackColor = this
.ForeColor;
367 
                }
368 

369                 //为刻度后面的表格设置颜色
370                 if (i >= _intDividerCell)
371 
                {
372                     cell.BackColor = this
.BackColor;
373 
                }
374 

375                 //刻度单元格分两部分设置颜色
376                 if (i == _intDividerCell)
377 
                {
378                     Table inner = (Table)cell.Controls[0
];
379                     if (inner.Rows[0].Cells.Count > 1
)
380 
                    {
381                         TableRow tr = inner.Rows[0
];
382                         tr.Cells[0].BackColor = this
.ForeColor;
383                         tr.Cells[1].BackColor = this
.BackColor;
384 
                    }
385                     else

386                     {
387                         inner.Rows[0].Cells[0].BackColor = this
.BackColor;
388 
                    }
389 
                }
390 
            }
391 

392             if (!TextStyle.DisplayTextAtBottom)
393 
            {
394                 outer.Rows[0].Cells[1
].ApplyStyle(TextStyle);
395                 outer.Rows[0].Cells[1].Width = Unit.Percentage(15
);
396 
            }
397             else if (TextStyle.RenderInsideTable &&
 TextStyle.DisplayTextAtBottom)
398 
            {
399                 TableRow row = t.Rows[1
];
400 
                row.ApplyStyle(TextStyle);
401 
            }
402             else

403             {
404                 Label lbl = (Label)this.Controls[1
];
405 
                lbl.ApplyStyle(TextStyle);
406 
            }
407 
        }
408 

409         #endregion
410     }
411 
}
412 

 

   2. 复合样式文件 TextItemStyle.cs 代码

  1 namespace KingControls
  2 
{
  3     /// <summary>

  4     /// Author: [ ChengKing(ZhengJian) ] 
  5     ///
 Blog:   Http://blog.csdn.net/ChengKing
  6     ///
 本代码 参照 Asp.net 2.0高级编程 方案
  7     /// </summary>

  8     /// <summary>
  9     /// 定义 SimpleGaugeBar 控件的内部复合属性类
 10     /// </summary>    

 11     public class TextItemStyle : TableItemStyle, IStateManager
 12 
    {
 13         #region 类变量

 14 
 15         private bool _renderInsideTable;
 16         private bool
 _displayTextAtBottom;
 17 

 18         #endregion
 19 
 20         #region 构造函数
 21 
 22         public TextItemStyle()
 23 
        {
 24             _displayTextAtBottom = true
;
 25             _renderInsideTable = false
;
 26 
        }
 27 

 28         #endregion
 29 
 30         #region 属性
 31 
 32         [NotifyParentProperty(true)]
 33         public bool
 RenderInsideTable
 34 
        {
 35             get

 36             {
 37                 return
 _renderInsideTable;
 38 
            }
 39             set

 40             {
 41                 _renderInsideTable =
 value;
 42 
            }
 43 
        }
 44 

 45         [NotifyParentProperty(true)] 
 46         public bool
 DisplayTextAtBottom
 47 
        {
 48             get

 49             {
 50                 return
 _displayTextAtBottom;
 51 
            }
 52             set

 53             {
 54                 _displayTextAtBottom =
 value;
 55 
            }
 56 
        }
 57 

 58         bool IStateManager.IsTrackingViewState
 59 
        {
 60             get

 61             {
 62                 return base
.IsTrackingViewState;
 63 
            }
 64 
        }
 65 

 66         #endregion
 67 
 68         #region 方法
 69         //从当前点开始, 此控件具有保存视图状态功能
 70         void IStateManager.TrackViewState()
 71 
        {
 72             base
.TrackViewState();
 73 
        }
 74 

 75         object IStateManager.SaveViewState()
 76 
        {
 77             object[] state = new object[2
];
 78             state[0= base
.SaveViewState();
 79             object[] others = new object[2
];
 80             others[0=
 _renderInsideTable;
 81             others[1=
 _displayTextAtBottom;
 82             state[1= (object
)others;
 83 

 84             //状态管理会存储此返回的值; 另外此方法返回值还有个用途: 创建复合控件时取得各个子控件的视图状态时使用
 85             return state;
 86 
        }
 87 

 88         void IStateManager.LoadViewState(object state)
 89 
        {
 90             if (state == null
)
 91 
            {
 92                 return
;
 93 
            }
 94             object[] myState = (object
[])state;
 95             base.LoadViewState(myState[0
]);
 96 

 97             object[] others = (object[])myState[1];
 98             _renderInsideTable = (bool)others[0
];
 99             _displayTextAtBottom = (bool)others[1
];
100 
        }
101 

102         #endregion
103     }
104 

105 }

(四). 扩展功能

         通过看上面代码可以看到,您可能会想到那些第三方公司开发的 WebChart 控件可以显示各种各样的复杂图形,而且不仅仅是柱状图, 还有饼状,折线图,甚至是 三维图形。以上代码仅演示了一个横向的单柱形图的做法。但已经足够说明实现一个 Chart 的过程。如果感兴趣,您可以试着扩展它, 比如: 先实现把示例代码的横向柱状图变为 竖向的柱状图; 再自己试着做一个 组合控件, 将多个本控件整合成一个可以同时显示多列的统计分析图; 更广一点, 再考虑做一个 饼图, 折线图等。


标签:

本站文章除注明转载外,均为本站原创或翻译。欢迎任何形式的转载,但请务必注明出处、不得修改原文相关链接,如果存在内容上的异议请邮件反馈至chenjj@evget.com

文章转载自:csdn

为你推荐

  • 推荐视频
  • 推荐活动
  • 推荐产品
  • 推荐文章
  • 慧都慧问
扫码咨询


添加微信 立即咨询

电话咨询

客服热线
023-68661681

TOP