【阿不】深入ASP.NET資料繫結(下)—多樣的繫結方式
在這個系列的上篇中介紹了資料繫結語法的原理以及.NET中如何實現單向繫結,中篇我們簡單的介紹了ASP.NET 2.0 中新增的Bind語法配合DataSourceControl來實現資料的自動雙向繫結。這兩部分的內容相對動態抽象並且不常接觸,沒有很好的原始碼支援很難解釋清楚,要想真正弄清它們的內部原理,還需要大家親自動手去反編譯分析動態編譯的程式集。
在瞭解了資料繫結語法的原理後,我還想來談談我中實踐過程中遇到的一些問題以及其它實用的繫結技巧。首先我們就來說說,特殊欄位名的問題。我們知道在資料庫當中,如果表名或欄位名中包含有一些特殊的不能是合法的字元時,都會使用[]將它們引起來,以便他們能夠正常使用。但是在的繫結語句當中,同時可以使用[],但是對於欄位名中包含 "(",")","[","]"這4個字元卻始終執行出錯。假設像我下面這樣來繫結"電壓(V)":
# Eval("電壓(V)")%>
那麼就會得到一個執行時錯誤:
DataBinding:“System.Data.DataRowView”不包含名為“電壓”的屬性。
表明括號是被認為是一個特殊字元,那我們如果給欄位名加上[],如下:
# Eval("[電壓(V)]")%>
電壓(V 既不是表 DataTable1 的 DataColumn 也不是 DataRelation。
表明,即使加上[]也無法解決這個特殊欄位名的問題。同時欄位名中如果也存在中括號,也是會出現這樣的問題的。但是這樣的欄位名卻在GridView的自動生成列中能被正常繫結呢?問題會出現在哪裡呢?分析和對比GridView的自動生成列與Eval這樣的繫結語法在最終執行繫結程式碼上的不同,我們可以發現,GridView的自動生成列取值並不是使用DataBinder.Eval這個方法,它內部有自己的取值方式,但是在實現上卻是大同小異的。那究竟是在哪裡出現了問題呢?我們找出DataBinder類的定義:
1: [AspNetHostingPermission(SecurityAction.LinkDemand, Level=200)]
2: public sealed class DataBinder
3: {
4: // Fields
5: private static readonly char[] expressionPartSeparator = new char[] { '.' };
6: private static readonly char[] indexExprEndChars = new char[] { ']', ')' };
7: private static readonly char[] indexExprStartChars = new char[] { '[', '(' };
8:
9: // Methods
10: public static object Eval(object container, string expression)
11: {
12: if (expression == null)
13: {
14: throw new ArgumentNullException("expression");
15: }
16: expression = expression.Trim();
17: if (expression.Length == 0)
18: {
19: throw new ArgumentNullException("expression");
20: }
21: if (container == null)
22: {
23: return null;
24: }
25: string[] expressionParts = expression.Split(expressionPartSeparator);
26: return Eval(container, expressionParts);
27: }
28:
29: private static object Eval(object container, string[] expressionParts)
30: {
31: object propertyValue = container;
32: for (int i = 0; (i < expressionParts.Length) && (propertyValue != null); i++)
33: {
34: string propName = expressionParts[i];
35: if (propName.IndexOfAny(indexExprStartChars) < 0)
36: {
37: propertyValue = GetPropertyValue(propertyValue, propName);
38: }
39: else
40: {
41: propertyValue = GetIndexedPropertyValue(propertyValue, propName);
42: }
43: }
44: return propertyValue;
45: }
46:
47: public static string Eval(object container, string expression, string format)
48: {
49: object obj2 = Eval(container, expression);
50: if ((obj2 == null) || (obj2 == DBNull.Value))
51: {
52: return string.Empty;
53: }
54: if (string.IsNullOrEmpty(format))
55: {
56: return obj2.ToString();
57: }
58: return string.Format(format, obj2);
59: }
60:
61: public static object GetDataItem(object container)
62: {
63: bool flag;
64: return GetDataItem(container, out flag);
65: }
66:
67: public static object GetDataItem(object container, out bool foundDataItem)
68: {
69: if (container == null)
70: {
71: foundDataItem = false;
72: return null;
73: }
74: IDataItemContainer container2 = container as IDataItemContainer;
75: if (container2 != null)
76: {
77: foundDataItem = true;
78: return container2.DataItem;
79: }
80: string name = "DataItem";
81: PropertyInfo property = container.GetType().GetProperty(name, BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);
82: if (property == null)
83: {
84: foundDataItem = false;
85: return null;
86: }
87: foundDataItem = true;
88: return property.GetValue(container, null);
89: }
90:
91: public static object GetIndexedPropertyValue(object container, string expr)
92: {
93: if (container == null)
94: {
95: throw new ArgumentNullException("container");
96: }
97: if (string.IsNullOrEmpty(expr))
98: {
99: throw new ArgumentNullException("expr");
100: }
101: object obj2 = null;
102: bool flag = false;
103: int length = expr.IndexOfAny(indexExprStartChars);
104: int num2 = expr.IndexOfAny(indexExprEndChars, length + 1);
105: if (((length < 0) || (num2 < 0)) || (num2 == (length + 1)))
106: {
107: throw new ArgumentException(SR.GetString("DataBinder_Invalid_Indexed_Expr", new object[] { expr }));
108: }
109: string propName = null;
110: object obj3 = null;
111: string s = expr.Substring(length + 1, (num2 - length) - 1).Trim();
112: if (length != 0)
113: {
114: propName = expr.Substring(0, length);
115: }
116: if<來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/12639172/viewspace-402162/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 【阿不】深入ASP.NET資料繫結(上)ASP.NET
- 【阿不】深入ASP.NET資料繫結(中)—資料雙向繫結機理ASP.NET
- 資料繫結
- 簡單資料繫結和複雜資料繫結
- ASP.NET MVC模型繫結——繫結部分欄位ASP.NETMVC模型
- Vue的資料繫結Vue
- angular 多選表單資料繫結Angular
- React事件繫結的方式React事件
- 資料繫結原理
- 第二講、Vue3.x繫結資料、繫結html、繫結屬性、迴圈資料VueHTML
- UWP中新加的資料繫結方式x:Bind分析總結
- javascript實現資料的雙向繫結(手動繫結)JavaScript
- uni-app入門教程(3)資料繫結、樣式繫結和事件處理APP事件
- springboot 配置多個資料來源,@MapperScan方式繫結Spring BootAPP
- 深入理解 C++ 的動態繫結和靜態繫結C++
- 資料繫結之謎
- 【Angular-資料繫結】Angular
- 2、理解資料繫結
- Angular | 理解資料繫結Angular
- Solaris下網路卡繫結多個IP
- Android下實現資料繫結功能Android
- angularjs中的資料繫結AngularJS
- Laravel 多鍵路由繫結Laravel路由
- VB.NET中怎樣為listview繫結資料View
- Vue資料繫結簡析Vue
- vue資料繫結原始碼Vue原始碼
- Binding(一):資料繫結
- JS雙向資料繫結JS
- SpringMVC資料繫結demoSpringMVC
- Flex 資料繫結備忘Flex
- 模板語法之--強制資料繫結和繫結事件監聽事件
- JavaScript 進階之深入理解資料雙向繫結JavaScript
- ASPxGridView的資料繫結顯示View
- 常用的前臺資料繫結方法
- 繫結class樣式和style樣式
- mysql繫結多個ip地址MySql
- angular1資料繫結例子Angular
- Vue資料雙向繫結原理Vue