zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    php多态
    ssl certificate problem: self signed certificate in certificate chain
    test plugin
    open specific port on ubuntu
    junit vs testng
    jersey rest service
    toast master
    use curl to test java webservice
    update folder access
    elk
  • 原文地址:https://www.cnblogs.com/CSharpSPF/p/2373287.html
Copyright © 2011-2022 走看看