WPF DataGrid自动生成行号

 

 

在使用WPF进行应用程序的开发时,常常会为DataGrid生成行号,这里主要介绍一下生成行号的方法。一般有三种方法,这里主要介绍其中的两种,另外一种简单提一下。post

1. 直接在LoadingRow事件中操做。this

这种方式是在code behind文件中操做。即相应的*.xaml.cs文件。spa

 代码以下:.net

复制代码
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文件中也能够。code

 

2. 正如在第一种方法末尾提到的,为了适应MVVM的开发模式,不但愿把自动生成行号的操做放到code behind文件中去实现,而也是想放到viewmodel中去实现。这时候可使用为事件绑定command的方法,具体作法见下面代码:xml

在设计页面中引入下面命名空间,该dll在安装blend后会存在,目录为C:\Program Files\Microsoft SDKs\Expression\Blend\.NETFramework\v4.0\Libraries,若是没有,本身能够到网上下载。blog

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

相关文章
相关标签/搜索