WPF DataGrid自動生成行號


在使用WPF進行應用程序的開發時,經常會為DataGrid生成行號,這里主要介紹一下生成行號的方法。通常有三種方法,這里主要介紹其中的兩種,另一種簡單提一下。

1. 直接在LoadingRow事件中操作。

這種方式是在code behind文件中操作。即相應的*.xaml.cs文件。

 代碼如下:

this.dataGridSoftware.LoadingRow +=  new EventHandler<DataGridRowEventArgs>( this.DataGridSoftware_LoadingRow);     

//  ...

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,如果沒有,自己可以到網上下載。

xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"  

 

為DataGrid設置EventTrigger, CommandParameter綁定datagrid本身,也就是將該datagrid作為command的參數。

< DataGrid  x:Name ="dataGridAllUsers" ... >
    < i:Interaction.Triggers >                                        
        < i:EventTrigger  EventName ="Loaded" >
            < i:InvokeCommandAction  Command =" {Binding Path=DatagridLoadedCommand} "
                                   CommandParameter
=" {Binding ElementName=dataGridAllUsers} " >                            
            </ i:InvokeCommandAction >
        </ i:EventTrigger >
     </ i:Interaction.Triggers >
</DataGrid>

 

ViewModel中的代碼,DatagridLoadedCommand的實現:

private ICommand 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

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM