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

(一). 概述

                本文主要演示一个比较简单的 WebChart 柱状实现,  可以一方面了解一个较完整的控件开发实例, 

        里面用到了复合样式及视图存储等内容.  另一方面了解一下WebChart的实现原理.  在Web开发中, 最终

        是用浏览器呈现各种图表,  图表控件呈现过程是 根据控件提供的属性接口接收到数据参数, 用最基本的

        Html元素<Table><tr><td>来呈现图表.  

        注:  本文参考 [Asp.net 2.0高级编程] 方案,  由于本书中配套代码说明链接打不开, 所以在文章最后面可以

               下载我上传的自己做得比较完整的示例代码.

 

(二). 运行效果

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

 

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

Asp.net 2.0 自定义控件开发[开发一个图表(WebChart)控件(柱状图示例)](示例代码下载)_第1张图片

           

                 主要属性用法介绍:  

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 的过程. 如果感兴趣, 您可

以试着扩展它, 比如: 先实现把示例代码的 横向柱状图变为 竖向的柱状图;  再自己试着做一个 组合控件, 将多

个本控件整合成一个可以同时显示多列的统计分析图;  更广一点, 再考虑做一个 饼图, 折线图等.

        

(五). 示例代码下载

        http://www.cnblogs.com/Files/MVP33650/SimpleGaugeBarControl.rar

 

(六). 控件开发其它相关文章:

        http://blog.csdn.net/ChengKing/category/288694.aspx

 

  

你可能感兴趣的:(Asp.net 2.0 自定义控件开发[开发一个图表(WebChart)控件(柱状图示例)](示例代码下载))