博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Asp.net 2.0 自定义控件开发[实现自动计算功能(AutoComputeControl)][示例代码下载]
阅读量:4190 次
发布时间:2019-05-26

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

(一). 概述        

 业余时间做了一个非常有用的控件, 介绍一下.

         一般当我们要实现这样一个计算功能页面:
                      TextBox1(单价)  * TextBox2(数量) = TextBox3(总和);
        并且当在TextBox1或TextBox2中输入数据, 鼠标离开时, TextBox3控件能够即时重新计算新值(乘积).
       一般我们的做法步骤是:
              
1. 拖三个控件到页面上, 默认三个TextBox控件ID分别为: TextBox1, TextBox1, 
                  TextBox3.
              
2. 写个JavaScript 函数, 能够计算 TextBox1和TextBox2的乘积, 并赋值给TextBox3
                  即时最新值.
                      
<script language='javascript'> 
                          function compute() 
                          {
                                  var _num 
= parseFloat(document.getElementById('TextBox1').value);
                                  var _price 
= parseFloat(document.getElementById('TextBox2').value);
                                  document.getElementById(
'TextBox3').value=_num*_price;
                         }
                      
script>
              
3. 注册TextBox1和TextBox2的onblur事件(TextBox控件失去焦点时触发).
                  
this.TextBox1.Attributes.Add("onblur","compute()");
                  
this.TextBox2.Attributes.Add("onblur","compute()"); 
             OK, 这样固然能够完成.  也存在以下缺点:
             
1. 不够通用, 如果好多页面都需要这么一个控件,  那得写上面这些代码到所有
                 页面中. 开发效率不高. 且容易出错.
             
2. 页面中代码比较乱. 嵌入好多JavaScript代码. 难以维护.
             
3. 假如运算表达式非常复杂[如:  A*B+(B*C)+Math.E  ] 每次设置JS也比较麻烦.
            基于以上缺陷,   
            下面是一个通用的自定义控件AutoComputeControl(自动计算),  能够弥补以上缺点, 
    且具有通用性, 
            特点如下:
              
1. 使用简单,  只需设置一个表达式属性Expression, 控件能够自动完成所有JS脚本.
                  其中表达式由: 运算符和变量组成(控件的ID), 等一下会详细介绍使用方法.
              
2. 不仅支持简单运算, 更大的优势是支持复杂表达式, 如:
                  price
*(num+2*(3+6))*Math.E = sum ,  即
                 TextBox1
*(TextBox2+2*(3+6)) * Math.E =TextBox3            
                  仅通过将控件的: ID和运算符 任意组合成计算表达式赋值给控件Expression属性, 
                  其它的工作由本控件来完成, 本控件能够自动生成所有JS脚本. 并最终在页面客
     户端呈现.  
             
3. 另外, 支持Math对象下面的属性和方法:
                       Math属性:   Math.E    Math.LN10 Math.LN2  Math.LOG10E  Math.LOG2E  
                                             Math.PI   Math.SQRT1_2     Math.SQRT2
                      Math方法:    Math.abs(x)   Math.acos(x)   Math.asin(x)   Math.atan(x)   
                                             Math.atan2(x,y)    Math.ceil(x)   Math.floor(x)   Math.cos(x) 
                                             Math.exp(x)   Math.log(x)   Math.max(x,y)   Math.min(x,y)   
                                             Math.pow(x,y)   Math.random()   Math.round(
20.49)   Math.sin(x)
                                             Math.sqrt(x)   Math.tan(x)
                       例如:   Math.sin(Math.sqrt(price1
*price2))+Math.E*num=sum
                           即    Math.sin(Math.sqrt(TextBox1
*TextBox2))+Math.E*TextBox3=TextBox4

             4. 最终用户还可以在控件中输入表达式:

                      例如, 用户在TextBox1框中输入: 6*(5+2)

                              再在TextBox2中输入: 3+Math.E*Math.PI

                              再把表达式: TextBox1*(TextBox2+2*(3+6)) * Math.E =TextBox3            

                              赋值给本控件属性Expression, 仍然能够正确计算出结果.

             5. 在一个页面中放多个本控件.

                 比如: 拖个本控件到页面跟 TextBox1/TextBox2/TextBox3 组合,

                         再拖另一个控件跟另一组  TextBox4/TextBox5/TextBox5  组合.

                 注意: 不要两组表达式产生冲突, 比如把TextBox1即在第一组又在

                         第二组, 这样脚本生成是正确的, 但这样自动生成的客户端脚本, 会

                         为TextBox1注册两个onblur事件, 那么默认第二个onblur起效, 不能

                         同时起效.  这是JavaScript 语法规定的.  

                                                

          实现原理:   本自定义控件的Expression属性, 如: TextBox1*(TextBox2+TexBox3)*0.90=TextBox4

                             中包括:

                                  1. 控件的ID.  2. 表达式之间的关系.

                             然后自定义控件内核代码会:

                                  1. 用编译算法扫描表达式属性(Expression)值, 分析运算关系.

                                  2. 根据运算关系动态生成要呈现到客户端的JavaScript, 再最终由自定义控件呈现.

(二).  使用步骤

         1. 拖三个TextBox控件到页面上,  如图:

        2. 设置TextBox1的ID属性为: price;   TextBox2的ID属性为: num;  TextBox3的ID属性为: sum.

        3. 再添加一个AutoCompute控件(本文章主讲控件), 并设置其: Expression 属性值为:

             price * num = sum ,  意思是: [单价] * [数量] = [总额]

        4. 运行即可.  运行后当输入[单价]和[数量]时, 程式能够自动计算[总额]的值.

            测试: 当鼠标从[单价]或[数量]控件失去焦点时, 总额值能够重新被计算显示.

       5. 扩展: 

               a. 您也可以输入更复杂的表达式, 比如从上面DropDownList(测试用的控件)里面随便选几个.

               b. 不仅能够计算三个TextBox的表达式(如上), 您还可以添加N个TextBox表达式.

        功能比较强大吧  :) :) 

(三). 表达式规则:

        支持JavaScript运算规则,  并支持Math对象的所有属性和方法.

(四). 核心代码

       1. Node类文件Node.cs, 用于编译算法中存储数据结点和字符结点

 1
/// 
 2    /// Author: [ ChengKing(ZhengJian) ] 
 3    /// Blog:   Http://blog.csdn.net/ChengKing
 4    /// 
 5    /// 
 6    /// Node 的摘要说明
 7    /// 
 8    /// 
 9    /// 结点类[操作符结点] 
10    /// 
11
    
public
 
class
 Node
12
    
{
13        public string str;       //存储本节点字串
14        public int startIndex;   //用于存储一个结点所在[运算表达式]的开始索引位置
15        public int endIndex;     //用于存储一个结点所在[运算表达式]的结束索引位置    
16
17
18        public Node(int startIndex, int endIndex, string str)
19        {
20            this.str = str;
21            this.startIndex = startIndex;
22            this.endIndex = endIndex;        
23        }
24    }

       2. 主要控件类 AutoCompute.cs 代码

 1 
///
 
 2     /// Author: [ ChengKing(ZhengJian) ] 
 3     /// Blog:   Http://blog.csdn.net/ChengKing
 4     /// 
 5 
    [DefaultProperty(
"
Text
"
)]
 6 
    [ToolboxData(
"
<{0}:AutoCompute runat=server>
"
)]
 7 
    
public
 
class
 AutoCompute : Control
 8 
    {
 9 
        [Bindable(
true
)]
10 
        
//
[Category("外观")]
11 
        [DefaultValue(
"
[AutoCompute /
"
AutoCompute1/
"
]
"
)]
12 
        [Localizable(
true
)]
13 
        
public
 
string
 Text
14 
        {
15 
            
get
16 
            {
17 
                String s 
=
 (String)ViewState[
"
Text
"
];
18 
                
return
 ((s 
==
 
null
?
 String.Empty : s);
19 
            }
20 
21 
            
set
22 
            {
23 
                ViewState[
"
Text
"
=
 value;
24 
            }
25 
        }
26 
27 
        [Bindable(
true
)]        
28 
        [DefaultValue(
""
)]
29 
        [Localizable(
true
)]
30 
        
public
 
string
 Expression
31 
        {
32 
            
get
33 
            {
34 
                
string
 s 
=
 (
string
)
this
.ViewState[
"
Expression
"
];
35 
                
return
 ((s 
==
 
null
?
 String.Empty : s);
36 
            }
37 
            
set
38 
            {
39 
                
this
.ViewState[
"
Expression
"
=
 value;
40 
            }
41 
        }
42 
43 
        
protected
 
override
 
void
 Render(HtmlTextWriter writer)
44 
        {
45 
            
if
 (DesignMode)
46 
            {
47 
                
this
.Controls.Clear();
48 
                LiteralControl lc 
=
 
new
 LiteralControl();
49 
                lc.Text 
=
 
this
.Text;
50 
                
this
.Controls.Add(lc);
51 
            }         
52 
            
base
.Render(writer);
53 
        }
54 
55 
        
protected
 
override
 
void
 OnPreRender(EventArgs e)
56 
        {
57 
            
base
.OnPreRender(e);
58 
59 
            ConvertHelper _ConvertHelper 
=
 
new
 ConvertHelper();
60 
            
string
 strClientScript;
61 
            
try
62 
            {
63 
                
if
 (
this
.Expression.Trim().Length 
!=
 
0
)
64 
                {
65 
                    _ConvertHelper.Main(Page, 
this
.Expression);
66 
                    _ConvertHelper.RegisterClientScript(
this
.Page);
67 
                }
68 
                
else
69 
                {
70 
                    strClientScript 
=
 
"
   alert('No Set [Expression] Property!');
"
;
71 
                    
if
 (
!
Page.ClientScript.IsStartupScriptRegistered(
"
Default_Property
"
))
72 
                    {
73 
                        Page.ClientScript.RegisterStartupScript(
this
.GetType(), 
"
Default_Property
"
, strClientScript, 
true
);
74 
                    }
75 
                }
76 
            }
77 
            
catch
78 
            {
79 
                strClientScript 
=
 
"
   alert('The [Expression] format is not correct!');
"
;
80 
                
if
 (
!
Page.ClientScript.IsStartupScriptRegistered(
"
Default_Property
"
))
81 
                {
82 
                    Page.ClientScript.RegisterStartupScript(
this
.GetType(), 
"
Default_Property
"
, strClientScript, 
true
);
83 
                }
84 
            }
85 
86 
        }
87 
88 
    }

       3. ConvertHelper.cs类文件, 主要实现编译算法以及JavaScript脚本生成注册功能.

  1 
 
///
 
  2     /// Author: [ ChengKing(ZhengJian) ] 
  3     /// Blog:   Http://blog.csdn.net/ChengKing
  4     /// 
  5 
    
///
 
  6     /// ConvertHelper 的摘要说明
  7     /// 
  8 
    
///
 
  9     /// 算法概述:
 10     ///  引用概念: [数据变量结点]: 用户命名的字串, 如: total = price*num, 则 "price" 字串就为数据变量结点
 11     ///  1. 抽取出操作运算符. 并记住所有运算符的索引
 12     ///  2. 两个操作符之间的字符串为[数据变量结点(用户命名的字串)], 但下面几种情况要排除:
 13     ///       a. 提取的相邻字符中, 右边字符为"("操作符时, 中间不是数据变量结点.
 14     ///       b. 两个操作符相邻时, 其中间没有字符串, 显然也就没有数据变量结点.
 15     ///       c. 数据变量结点必须是字符串变量, 不能为数值.
 16     ///       d. 排除Math.E等常量情况(Math.E/Math.LN10/Math.LN2/Math.LOG10E/Math.LOG2E/ Math.PI/Math.SQRT1_2/Math.SQRT2).
 17     /// 
 18 
    
public
 
class
 ConvertHelper
 19 
    {
 20 
        
///
 
 21         /// 存放JavaScript运算符的各种结点
 22         /// 
 23 
        
private
 
string
[] OP_Chars 
=
 
new
 
string
[
7
] { 
"
+
"
"
-
"
"
*
"
"
/
"
"
(
"
"
)
"
"
,
"
 };
 24 
 25 
        
///
 
 26         /// 自定义变量前缀符号
 27         /// 
 28 
        
private
 
string
 VarPreSymbol 
=
 
"
_
"
;
 29 
 30 
        
///
 
 31         /// 存储要读取控件的属性(如: t.text/t.Value etc)
 32         /// 
 33 
        
private
 
string
 ValueSymbol 
=
 
"
.value
"
;
 34 
 35 
        
///
 
 36         /// 存储compute方法脚本变量
 37         /// 
  
 38 
        
private
 
string
 ComputeScript 
=
 
""
;
 39 
 40 
        
///
 
 41         /// 存储onblur方法脚本变量
 42         /// 
  
 43 
        
private
 
string
 OnblurScript 
=
 
""
;
 44 
 45 
        
///
 
 46         /// 区别于方法名的序列号[依次递增, 如: compute1, compute2, compute3  ]
 47         /// 
 48 
        
private
 
int
 SequenceNum 
=
 
1
;
 49 
 50 
        
///
 
 51         /// 抽取出运算符结点[其中包括运算符结点的位置信息]
 52         /// 
 53 
        
///
 
 54 
        
///
 
 55 
        
private
 List
<
Node
>
 BuildOPNode(
string
 strObject)
 56 
        {
 57 
            
int
 beginIndex 
=
 
0
//
记录当前处理结点的起始索引       
 58 
            List
<
Node
>
 nodes 
=
 
new
 List
<
Node
>
();
 59 
 60 
 61 
            
while
 (
true
)
 62 
            {
 63 
                
if
 (beginIndex 
==
 strObject.Length)
 64 
                {
 65 
                    
break
;
 66 
                }
 67 
 68 
                
for
 (
int
 j 
=
 
0
; j 
<
 OP_Chars.Length; j
++
)
 69 
                {
 70 
                    
if
 (strObject.Length 
-
 beginIndex 
>=
 OP_Chars[j].Length)
 71 
                    {
 72 
                        
if
 (OP_Chars[j] 
==
 strObject.Substring(beginIndex, OP_Chars[j].Length))
 73 
                        {
 74 
                            
//
操作符
 75 
                            Node node 
=
 
new
 Node(beginIndex, beginIndex 
+
 OP_Chars[j].Length 
-
 
1
, strObject.Substring(beginIndex, OP_Chars[j].Length));
 76 
                            nodes.Add(node);
 77 
                            
break
;
 78 
                        }
 79 
                    }
 80 
                }
 81 
                beginIndex
++
;
 82 
            }
 83 
            
return
 nodes;
 84 
        }
 85 
 86 
        
///
 
 87         /// 根据运算符结点抽取出数据结点[其中包括数据结点的位置信息]
 88         /// 
 89 
        
///
 
 90 
        
///
 
 91 
        
public
 List
<
Node
>
 BuildDataNode(
string
 strObject)
 92 
        {
 93 
            strObject 
=
 ClearSpace(strObject);
 94 
            List
<
Node
>
 dataNodes 
=
 
new
 List
<
Node
>
();
 95 
            List
<
Node
>
 opNodes 
=
 
this
.BuildOPNode(strObject);
 96 
 97 
            
//
考虑表达式最左边是数据结点情况, 如: A+B 表达式中的A
 98 
            
if
 (opNodes.Count 
>
 
0
 
&&
 opNodes[
0
].startIndex 
!=
 
0
 
&&
 opNodes[
0
].str 
!=
 
"
(
"
)
 99 
            {
100 
                
string
 str 
=
 strObject.Substring(
0
, opNodes[
0
].startIndex);
101 
                
if
 (
this
.JudgeFigure(str) 
==
 
false
 
&&
 
this
.IsIndexOfMath(str) 
==
 
false
)
102 
                {
103 
                    Node node 
=
 
new
 Node(
0
, opNodes[
0
].startIndex 
-
 
1
, str);
104 
                    dataNodes.Add(node);
105 
                }
106 
107 
            }
108 
109 
            
//
根据操作运算符求得中间的一系列数据结点
110 
            
for
 (
int
 i 
=
 
0
; i 
<
 opNodes.Count 
-
 
1
; i
++
)
111 
            {
112 
                
if
 (
this
.IsDataNodeBetweenOPNodes(opNodes[i], opNodes[i 
+
 
1
], strObject))
113 
                {
114 
                    Node node 
=
 
new
 Node(opNodes[i].endIndex 
+
 
1
, opNodes[i 
+
 
1
].startIndex 
-
 
1
, strObject.Substring(opNodes[i].endIndex 
+
 
1
, opNodes[i 
+
 
1
].startIndex 
-
 opNodes[i].endIndex 
-
 
1
));
115 
                    dataNodes.Add(node);
116 
                }
117 
            }
118 
119 
            
//
考虑最右端是数据结点情况, 如: A+B 表达式中的B
120 
            
if
 (opNodes.Count 
>
 
0
 
&&
 (opNodes[opNodes.Count 
-
 
1
].endIndex 
!=
 strObject.Length 
-
 
1
))
121 
            {
122 
                
string
 str 
=
 strObject.Substring(opNodes[opNodes.Count 
-
 
1
].endIndex 
+
 
1
);
123 
                
if
 (
this
.JudgeFigure(str) 
==
 
false
 
&&
 
this
.IsIndexOfMath(str) 
==
 
false
)
124 
                {
125 
                    Node node 
=
 
new
 Node(opNodes[opNodes.Count 
-
 
1
].endIndex 
+
 
1
, strObject.Length 
-
 
1
, str);
126 
                    dataNodes.Add(node);
127 
                }
128 
            }
129 
            
return
 dataNodes;
130 
        }
131 
132 
        
///
 
133         /// 判断相邻结点中间是否是数据结点
134         /// 
135 
        
///
 
136 
        
///
 
137 
        
///
 
138 
        
///
  根据以下定理进行判断
139 
        
///
    a. 提取的相邻字符中, 右边字符为"("操作符时, 中间不是数据变量结点.
140 
        
///
    b. 两个操作符相邻时, 其中间没有字符串, 显然也就没有数据变量结点.
141 
        
///
    c. 数据变量结点必须是字符串变量, 不能为数值.
142 
        
///
    d. 排除Math.E等常量情况(Math.E/Math.LN10/Math.LN2/Math.LOG10E/Math.LOG2E/ Math.PI/Math.SQRT1_2/Math.SQRT2).
143 
        
private
 
bool
 IsDataNodeBetweenOPNodes(Node leftNode, Node rightNode, 
string
 strObject)
144 
        {
145 
            
//
条件a
146 
            
if
 (rightNode.str 
==
 
"
(
"
)
147 
            {
148 
                
return
 
false
;
149 
            }
150 
151 
            
//
条件b
152 
            
if
 (leftNode.endIndex 
+
 
1
 
==
 rightNode.startIndex)
153 
            {
154 
                
return
 
false
;
155 
            }
156 
157 
            
//
条件c
158 
            
if
 (
this
.JudgeFigure(strObject.Substring(leftNode.endIndex 
+
 
1
, rightNode.startIndex 
-
 leftNode.endIndex 
-
 
1
)) 
==
 
true
)
159 
            {
160 
                
return
 
false
;
161 
            }                   
162 
            
163 
            
if
 (
this
.IsIndexOfMath(strObject.Substring(leftNode.endIndex 
+
 
1
, rightNode.startIndex 
-
 leftNode.endIndex 
-
 
1
)))
164 
            {
165 
                
return
 
false
;
166 
            }
167 
168 
            
return
 
true
;
169 
        }
170 
171 
        
///
 
172         /// //判断是否Math.开头 排除(Math.E/Math.LN10/Math.LN2/Math.LOG10E/Math.LOG2E/ Math.PI/Math.SQRT1_2/Math.SQRT2)等常量
173         /// 
174 
        
///
 
175 
        
///
 
176 
        
public
 
bool
 IsIndexOfMath(
string
 str)
177 
        {
178 
            
if
 (str.IndexOf(
"
Math.
"
==
 
0
)
179 
            {
180 
                
return
 
true
;
181 
            }
182 
            
return
 
false
;
183 
        }
184 
185 
        
///
 
186         /// 判断是否是数字
187         /// 
188 
        
///
 
189 
        
///
 
190 
        
private
 
bool
 JudgeFigure(
string
 str)
191 
        {
192 
            
if
 (str.Trim().Length 
<=
 
0
)
193 
                
return
 
true
;
194 
            
int
 dot 
=
 
0
;
195 
            
if
 (str[
0
==
 
'
.
'
 
||
 str[str.Length 
-
 
1
==
 
'
.
'
)
196 
                
return
 
false
;
197 
            
for
 (
int
 i 
=
 
0
; i 
<
 str.Length; i
++
)
198 
            {
199 
                
if
 (dot 
>
 
1
return
 
false
;
200 
                
if
 (Char.IsDigit(str, i))
201 
                {
202 
                    
continue
;
203 
                }
204 
                
if
 (str[i] 
==
 
'
.
'
)
205 
                {
206 
                    dot 
=
 dot 
+
 
1
;
207 
                    
continue
;
208 
                }
209 
                
return
 
false
;
210 
            }
211 
            
return
 
true
;
212 
        }
213 
214 
        
///
 
215         /// 返回处理后的表达式
216         /// 
217 
        
///
 
218 
        
///
 
219 
        
///
 
220 
        
private
 
string
 CreateClientScript(Page page, 
string
 strAll, List
<
Node
>
 nodes)
221 
        {
222 
            
string
 strLeft 
=
 strAll.Substring(
0
, strAll.IndexOf(
"
=
"
)); ;
223 
            
string
 strRight 
=
 strAll.Substring(strAll.IndexOf(
"
=
"
)
+
1
);
224 
225 
            
///
 
226             /// 生成并注册compute方法脚本
227             /// 
228 
            
int
 intNumDataNodeCount 
=
 nodes.Count;
229 
230 
            
//
调整方法名, 防止多个表达式运算时, 方法名冲突
231 
            
while
 (
true
)
232 
            {
233 
                
//
bool flag = page.ClientScript.IsClientScriptBlockRegistered("compute" + SequenceNum.ToString());
234 
                
if
 (
!
page.ClientScript.IsClientScriptBlockRegistered(
this
.GetType(), 
"
compute
"
 
+
 SequenceNum.ToString()))
235 
                {
236 
                    
if
 (
!
page.ClientScript.IsStartupScriptRegistered(
this
.GetType(), 
"
onblur
"
 
+
 
this
.SequenceNum.ToString()))
237 
                    {
238 
                        
break
;
239 
                    }
240 
241 
                }
242 
                SequenceNum
++
;
243 
            }
244 
245 
            
//
生成脚本头JS字串
246 
            
string
 strJSHead 
=
 
"
<script language='javascript'> /n function compute
"
 
+
 
this
.SequenceNum.ToString() 
+
 
"
() /n { /n
"
;            
247 
            
//
生成脚本体JS字串
248 
            
string
 strJSBody 
=
 
""
;
249 
            
for
 (
int
 i 
=
 
0
; i 
<
 intNumDataNodeCount; i
++
)
250 
            {
251 
                strJSBody 
+=
 
"
  var 
"
 
+
 VarPreSymbol 
+
 nodes[i].str 
+
 
"
 = parseFloat(document.getElementById('
"
 
+
 ((Control)page.FindControl(nodes[i].str)).ClientID 
+
 
"
')
"
 
+
 ValueSymbol 
+
 
"
);/n
"
;  
252 
            }
253 
            strJSBody 
+=
 
"
  document.getElementById('
"
 
+
 ((Control)page.FindControl(strRight)).ClientID 
+
 
"
')
"
 
+
 ValueSymbol; 
254 
            strJSBody 
+=
 
"
=
"
;
255 
256 
            
for
 (
int
 i 
=
 
0
; i 
<
 intNumDataNodeCount; i
++
)
257 
            {
258 
                strLeft 
=
 strLeft.Remove(nodes[i].startIndex, nodes[i].str.Length);
259 
                strLeft 
=
 strLeft.Insert(nodes[i].startIndex, 
"
_
"
 
+
 nodes[i].str);
260 
                
this
.RepairNodes(
ref
 nodes, i 
+
 
1
);
261 
            }
262 
            strLeft 
+=
 
"
;
"
;
263 
            strJSBody 
+=
 strLeft;
264 
            
string
 strJSFoot 
=
 
"
/n }/n</script>/n/n
"
;
265 
266 
            
string
 strReturnScript 
=
 strJSHead 
+
 strJSBody 
+
 strJSFoot;
267 
            
this
.ComputeScript 
=
 strReturnScript;
268 
269 
270 
271 
            
///
 
272             /// 生成并注册onblur脚本(调用compute方法)
273             /// 
274 
            
string
 strOnBlur 
=
 
"
/n<script language='javascript'>/n
"
;
275 
            
for
 (
int
 i 
=
 
0
; i 
<
 nodes.Count; i
++
)
276 
            {                
277 
                strOnBlur 
+=
 
"
  document.getElementById('
"
 
+
 ((Control)page.FindControl(nodes[i].str)).ClientID 
+
 
"
')
"
 
+
 
"
.οnblur=compute
"
 
+
 
this
.SequenceNum.ToString() 
+
 
"
;/n
"
;
278 
            }
279 
            strOnBlur 
+=
 
"
</script>
"
;
280 
            
this
.OnblurScript 
=
 strOnBlur;
281 
282 
283 
284 
            strReturnScript 
+=
 strOnBlur;
285 
            
return
 strReturnScript;
286 
        }
287 
288 
        
///
 
289         /// 重新调整数据节点集合的索引值
290         /// 
291 
        
///
 
292 
        
///
 
293 
        
private
 
void
 RepairNodes(
ref
 List
<
Node
>
 nodes, 
int
 index)
294 
        {
295 
            
for
 (
int
 i 
=
 index; i 
<
 nodes.Count; i
++
)
296 
            {
297 
                
//
6相当于前面数据结点插入的 ".value" 的长度
298 
                nodes[i].startIndex 
=
 nodes[i].startIndex 
+
 VarPreSymbol.Length;
299 
                nodes[i].endIndex 
=
 nodes[i].endIndex 
+
 VarPreSymbol.Length;
300 
            }
301 
        }
302 
303 
        
public
 
string
 Main(Page page, 
string
 strAll)
304 
        {
305 
            strAll 
=
 
this
.ClearSpace(strAll);
306 
            
if
 (CheckParenthesesMatching(strAll) 
==
 
false
)
307 
            {
308 
                page.Response.Write(
"
 括号不匹配!
"
);
309 
                
return
 
""
;
310 
            }
311 
312 
            
string
 strLeft 
=
 strAll.Substring(
0
, strAll.IndexOf(
"
=
"
));
313 
314 
            
string
 strEndJS_Script 
=
 
this
.CreateClientScript(page, strAll, BuildDataNode(strLeft));
315 
            
return
 strEndJS_Script;
316 
        }
317 
318 
        
//
检查括号是否匹配
319 
        
private
 
bool
 CheckParenthesesMatching(
string
 strCheck)
320 
        {
321 
            
int
 number 
=
 
0
;
322 
            
for
 (
int
 i 
=
 
0
; i 
<
 strCheck.Length; i
++
)
323 
            {
324 
                
if
 (strCheck[i] 
==
 
'
(
'
) number
++
;
325 
                
if
 (strCheck[i] 
==
 
'
)
'
) number
--
;
326 
                
if
 (number 
<
 
0
return
 
false
;
//
右括号不能在前面
327 
            }
328 
            
if
 (number 
!=
 
0
)
329 
            {
330 
                
return
 
false
;
331 
            }
332 
            
return
 
true
;
333 
        }
334 
335 
        
//
消去空格
336 
        
private
 
string
 ClearSpace(
string
 str)
337 
        {
338 
            
return
 str.Replace(
"
 
"
""
);
339 
        }
340 
341 
        
//
注册客户端脚本
342 
        
public
 
bool
 RegisterClientScript(Page page)
343 
        {
344 
            
if
 (
this
.OnblurScript.Length 
==
 
0
 
||
 
this
.ComputeScript.Length 
==
 
0
)
345 
            {
346 
                
return
 
false
;
347 
            }
348 
349 
            
if
 (
!
page.ClientScript.IsClientScriptBlockRegistered(
"
compute
"
 
+
 
this
.SequenceNum.ToString()))
350 
            {
351 
                page.ClientScript.RegisterClientScriptBlock(
this
.GetType(), 
"
compute
"
this
.ComputeScript, 
false
);
352 
            }
353 
354 
            
if
 (
!
page.ClientScript.IsStartupScriptRegistered(
"
onblur
"
 
+
 
this
.SequenceNum.ToString()))
355 
            {
356 
                page.ClientScript.RegisterStartupScript(
this
.GetType(), 
"
onblur
"
this
.OnblurScript, 
false
);
357 
            }
358 
            
return
 
true
;
359 
        }
360 
361 
    }

 

(五). 示例代码下载

          

(六). 其它相关自定义控件文章

       

 

(七).此控件的第二个版本源码已经发布, 请看这里, 内容更精彩:

 

 

   

 

 

 

 

 

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

你可能感兴趣的文章
微软宣布将推出XNA Game Studio
查看>>
MySQL宣布加入微软Visual Studio工业伙伴计划
查看>>
菜鸟、夫子、玫林凯与测试
查看>>
无锁编程与分布式编程那个更适合多核CPU?
查看>>
多核系统中三种典型锁竞争的加速比分析
查看>>
多核新观念-象使用内存一样使用CPU?
查看>>
OpenMP创建线程中的锁及原子操作性能比较
查看>>
多核编程中的任务随机竞争模式的概率分析
查看>>
多核编程中的任务分组竞争模式
查看>>
模块分解原理与三权分立
查看>>
模块分解原理的探索
查看>>
90%程序员写不出无BUG的二分查找程序?
查看>>
C/C++代码检视要点
查看>>
Symbian中所体现的软件编程艺术
查看>>
c/c++中指针参数如何传递内存
查看>>
Symbian程序图标问题
查看>>
虚基类释义
查看>>
虚函数释义
查看>>
自动记录上次登陆成功的用户信息
查看>>
基于回合制的在线棋类对战游戏(图)
查看>>