在使用WPF進行應用程序的開發時,經常會為DataGrid生成行號,這里主要介紹一下生成行號的方法。通常有三種方法,這里主要介紹其中的兩種,另一種簡單提一下。
1. 直接在LoadingRow事件中操作。
這種方式是在code behind文件中操作。即相應的*.xaml.cs文件。
代碼如下:
// ...
private void DataGridSoftware_LoadingRow( object sender, DataGridRowEventArgs e)
{
e.Row.Header = e.Row.GetIndex() + 1;
}
這種方式最為簡潔,也最容易理解。
但現在很多應用程序的開發都采用了MVVM(Model-View-ModelView)的開發模式。這種模式通常為了更好的解耦,所以通常不會在code behind文件中加入代碼,為了在這種方式下實現上面的自動生成行號的操作,可以采用下面要講到第二種方法。但我個人認為,不能太死板的使用MVVM,對於生成行號這種需求,不是業務邏輯的范疇,而是view的范疇,所以放到code behind文件中也可以。
2. 正如在第一種方法末尾提到的,為了適應MVVM的開發模式,不希望把自動生成行號的操作放到code behind文件中去實現,而也是想放到viewmodel中去實現。這時候可以使用為事件綁定command的方法,具體做法見下面代碼:
在設計頁面中引入下面命名空間,該dll在安裝blend后會存在,目錄為C:\Program Files\Microsoft SDKs\Expression\Blend\.NETFramework\v4.0\Libraries,如果沒有,自己可以到網上下載。
為DataGrid設置EventTrigger, CommandParameter綁定datagrid本身,也就是將該datagrid作為command的參數。
< i:Interaction.Triggers >
< i:InvokeCommandAction Command =" {Binding Path=DatagridLoadedCommand} "
CommandParameter =" {Binding ElementName=dataGridAllUsers} " >
</ i:InvokeCommandAction >
</ i:EventTrigger >
</ i:Interaction.Triggers >
ViewModel中的代碼,DatagridLoadedCommand的實現:
public ICommand DatagridLoadedCommand
{
get
{
if ( this.datagridLoadedCommand == null)
{
this.datagridLoadedCommand = new RelayCommand(
param =>
{
/// / Get the passed dataGrid.
System.Windows.Controls.DataGrid dataGrid = (System.Windows.Controls.DataGrid)param;
/// / After loaded, change all the row header to asending number.
foreach ( var v in dataGrid.Items)
{
System.Windows.Controls.DataGridRow dgr = (System.Windows.Controls.DataGridRow)dataGrid.ItemContainerGenerator.ContainerFromItem(v);
if (dgr != null)
{
dgr.Header = dgr.GetIndex() + 1;
}
else
{
/// / At this point, the v is not loaded into the DataGrid, so it will be null
/// / Once you scroll the datagrid, it begins loading, and it will trigger the LoadingRow event
/// / As we registered in following code lines, the line number will generated automatically.
break;
}
}
/// / Rgister the LoadingRow event.
dataGrid.LoadingRow += (sender, e) => { e.Row.Header = e.Row.GetIndex() + 1; };
});
}
return this.datagridLoadedCommand;
}
}
由於是Loaded事件之后才注冊LoadingRow事件,所以一開始加載的數據並沒有行號。所以想着是不是綁定其他的事件比較好呢,也沒有找到。如果你找到,歡迎分享。為了在加載好DataGrid之后顯示行號,需要循環datagrid的所有行,然后修改DataGridRow.Header屬性,這就是Command中那個foreach語句的作用。還有一點要注意的是,假如datagrid有很多數據,在可視范圍內沒有顯示完全(有滾動條),datagrid只加載可視范圍內的數據(items),其他數據在拖動滾動條要查看時才加載,但其Items集合屬性包含了所有item,所以foreach里面多了個if語句來判斷,如果取到的DataGridRow為空時,說明可視范圍內的行號已更新完畢,這時可以終止循環,注冊LoadingRow事件即可。當其他items加載的時候就會自動觸發該事件改變行號了。
雖然這種方式可以實現自動生成行號的功能,但給人感覺也不爽,畢竟還是在ViewModel中操作具體控件的。
3. 第三種方法是在為DataGrid生成數據源時,在集合中加一index列。在數據源變更時也更新這一列,這種方式我沒試,覺得更麻煩。
最后,你可能會想,如果在第二種方法中,如果能夠把LoadingRow事件的參數作為command的參數,那么viewmodel中的command的實現就可以像第一種方法中一樣簡單了。下面有一篇關於MVVM中實現Command綁定獲取事件參數EventArgs的做法,可以參考:http://blog.csdn.net/qing2005/article/details/6680047
