博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Asp.net 2.0 自定义控件开发[开发一个图表(WebChart)控件(柱状图示例)](示例代码下载)
阅读量:4190 次
发布时间:2019-05-26

本文共 11400 字,大约阅读时间需要 38 分钟。

(一). 概述

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

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

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

        Html元素

来呈现图表.  

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

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

 

(二). 运行效果

      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 
    
///
 
  4     /// Author: [ ChengKing(ZhengJian) ] 
  5     /// Blog:   Http://blog.csdn.net/ChengKing
  6     /// 本代码 参照 Asp.net 2.0高级编程 方案
  7     /// 
  8 
    [DefaultProperty(
"
Value
"
)]
  9 
    [ToolboxData(
"
<{0}:SimpleGaugeBar runat=server>
"
)]
 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 
        
///
 
 24         /// 进度条值
 25         /// 
 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 
        
///
 
 46         /// 全值
 47         /// 
 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 
        
///
 
 66         /// 表示进度条分几段
 67         /// 
 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 
        
///
 
 90         /// 文本呈现格式
 91         /// 
 92 
        
public
 
string
 FormatString
 93 
        {
 94 
            
get
 95 
            {
 96 
                
object
 o 
=
 
this
.ViewState[
"
FormatString
"
];
 97 
                
if
 (o 
==
 
null
)
 98 
                {
 99 
                    
return
 
"
{0}/{1}
"
;
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 
        
///
 
169         /// 在Web开发中,用Table/TR/TD来表示图形输出
170         /// 
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 
        
///
 
199         /// 用Label来呈现文本,如: { 8/10 }
200         /// 
201 
        
///
 
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 
        
///
 
292         /// 创建最外Table的第二行, 显示文本
293         /// 
294 
        
///
 
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 
        
///
 
328         /// 增加样式
329         /// 
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 
    
///
 
  4     /// Author: [ ChengKing(ZhengJian) ] 
  5     /// Blog:   Http://blog.csdn.net/ChengKing
  6     /// 本代码 参照 Asp.net 2.0高级编程 方案
  7     /// 
  8 
    
///
 
  9     /// 定义 SimpleGaugeBar 控件的内部复合属性类
 10     /// 
    
 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 的过程. 如果感兴趣, 您可

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

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

        

(五). 示例代码下载

       

 

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

       

 

 

 

 

 

 

 

 

 

 

 

 

 

   

Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1786409

你可能感兴趣的文章
代码自动生成和抽象
查看>>
权衡的艺术
查看>>
软件测试认识中的误区
查看>>
Slashdot对Bjarne Stroustrup的采访
查看>>
递归之美 - Loki库TypeList源码剖析
查看>>
基于hibernate的das实现研究(4)
查看>>
基于hibernate的das实现研究(3)
查看>>
基于hibernate的das实现研究(1)
查看>>
基于hibernate的das实现研究(2)
查看>>
eclipse的jre设置
查看>>
世界是平的------说说SOA,jini,jxta,jbi,OSGi
查看>>
1.1 jBPM BPEL的wsdl扩展实现
查看>>
手机流媒体技术概要
查看>>
SOA和伪技术
查看>>
BPEL1.1的activity类图说明及BPEL2.0新加功能
查看>>
凭借BPEL和ESB JBoss发力SOA
查看>>
我对SOA的理解
查看>>
smart_jsp1.2发布了
查看>>
smart发布中发现的weblogic/tomcat/resin的兼容性问题以及解决方案
查看>>
在SourceForge.net上使用TortoiseCVS上传代码
查看>>