CollectionBase 支持IList 接 口,所以你可以使用它來進行數據綁定。現在,你就發現了你的第一個問題:如 果地址為空,你的所有數據綁定行就失敗了。而這在DataSet裡是不會發生的。 數據綁定是由基於反射的遲後綁定代碼組成的。控件使用反射來加載列表裡的第 一個元素,然後使用反射來決定它的類型以及這個類型上的所有成員屬性。這就 是為什麼DataGrid可以知道什麼列要添加。它會在集合中的第一個元素上發現所 有的公共屬性,然後顯示他們。當集合為空時,這就不能工作了。你有兩種可能 來解決這個問題。第一個方法有點丑,但是一個簡單的方法:那就是不充許有空 列表存在。第二個好一些,但要花點時間:那就是實現ITypedList 接口。 ITypedList 接口提供了兩個方法來描述集合中的類型。GetListName 返回一個 可讀的字符串來描述這個列表。GetItemPropertIEs 則返回 PropertyDescriptors 列表,這是用於描述每個屬性的,它要格式化在表格裡的 :
public class AddressList : CollectionBase
{
public string GetListName(
PropertyDescriptor[ ] listAccessors )
{
return "AddressList";
}
public PropertyDescriptorCollection
GetItemPropertIEs(
PropertyDescriptor[ ] listAccessors)
{
Type t = typeof( AddressRecord );
return TypeDescriptor.GetPropertIEs( t );
}
}
這稍微 好一點了,現在你你已經有一個集合可以支持簡單的數據綁定了。盡管,你失去 了很多功能。下一步就是要實現數據對事務的支持。如果你使用過DataSet,你 的用戶可以通過按Esc鍵來取消DataGrid中一行上所有的修改。例如,一個用戶 可能輸入了錯誤的城市,按了Esc,這時就要原來的值恢復過來。DataGrid同樣 還支持錯誤提示。你可以添加一個ColumnChanged 事件來處理實際列上的驗證原 則。例如,州的區號必須是兩個字母的縮寫。使用框架裡的DataSet,可以這樣 寫代碼:
ds.Tables[ "Addresses" ].ColumnChanged +=new
DataColumnChangeEventHandler( ds_ColumnChanged );
private void ds_ColumnChanged( object sender,
DataColumnChangeEventArgs e )
{
if ( e.Column.ColumnName == "State" )
{
string newVal = e.ProposedValue.ToString( );
if ( newVal.Length != 2 )
{
e.Row.SetColumnError( e.Column,
"State abbreviation must be two letters" );
e.Row.RowError = "Error on State";
}
else
{
e.Row.SetColumnError( e.Column,
"" );
e.Row.RowError = "";
}
}
}