【问题标题】:WPF DataGrid - Event for New Rows?WPF DataGrid - 新行的事件?
【发布时间】:2011-01-06 17:33:11
【问题描述】:

我正在使用 WPF DataGrid.Net 3.5 SP 1 版本来自 Toolkit

我可以订阅什么事件来检测何时添加了新行? (例如,当用户向下移动光标或按下 Enter 时,一个新的空白行被添加到网格中)。

最终我想做的是使用该事件来计算一些默认值并将它们放在新行中。

网格绑定到DataTable,如果这有什么不同的话。

【问题讨论】:

    标签: c# wpf datagrid


    【解决方案1】:

    您要查找的事件是DataGrid.AddingNewItem event。此事件将允许您根据需要配置新对象,然后将其应用于AddingNewItemEventArgsNewItem 属性。

    XAML:

    <DataGrid Name="GrdBallPenetrations"
          ItemsSource="{Binding BallPenetrationCollection}" 
          SelectedItem="{Binding CurrentSelectedBallPenetration}"
          AutoGenerateColumns="False" 
          IsReadOnly="False"
          CanUserAddRows="True"
          CanUserDeleteRows="True"
          IsSynchronizedWithCurrentItem="True"
          AddingNewItem="GrdBallPenetrations_AddingNewItem">
    

    C# 中的代码:

    private void GrdBallPenetrations_AddingNewItem(object sender,
        AddingNewItemEventArgs e)
    {
        e.NewItem = new BallPenetration
        {
            Id              = Guid.NewGuid(),
            CarriageWay     = CariageWayType.Plus,
            LaneNo          = 1,
            Position        = Positions.BetweenWheelTracks
        };
    }
    

    【讨论】:

    • 我只是想提一下,对于那些仍在使用旧版本 .Net 框架的人来说,直到 .Net 4.5 才可用。
    • 如果项目是通过ItemsSource 绑定添加的,则不会触发AddingNewItem 事件。
    • @wondra,正确的。该事件仅根据用户输入与网格的交互触发。这是根据用户与网格的交互来初始化新数据实例的最佳位置。从网格的角度来看,您对 ItemsSource 所做的任何更改都是来自您的数据存储而不是来自用户的更改。试图操纵 ItemsSource 以初始化新对象将破坏用户与网格的交互。
    【解决方案2】:

    当用户离开他正在编辑的行时,对象会被持久化(插入或更新)。移动到同一行中的另一个单元格会通过数据绑定更新相应的属性,但尚未向模型(或数据访问层)发出信号。唯一有用的事件是 DataGrid.RowEditEnding。这是在提交修改的行之前触发的。

    XAML

    <DataGrid ... 
              RowEditEnding="MyDataGrid_RowEditEnding">
    </DataGrid>
    

    代码背后

    private void MyDataGrid_RowEditEnding(object sender, DataGridRowEditEndingEventArgs e) 
    {    // Only act on Commit
        if (e.EditAction == DataGridEditAction.Commit)
        {
             var newItem = e.Row.DataContext as MyDataboundType;
             if (newItem is NOT in my bound collection) ... handle insertion...
        } 
    }
    

    此解决方案的所有功劳归于 Diederik Krolls (Original Post)。尊敬的。

    【讨论】:

      【解决方案3】:

      我建议不要在 View(网格)中处理事件,而是观看绑定的对象,并将逻辑放在那里。这使您的业务逻辑与您的业务对象保持一致。

      由于您已绑定到DataTable,因此最简单的方法是订阅DataTable.TableNewRow

      【讨论】:

      • 我完全同意。这会给你更多的灵活性。例如,在未来的某一天,您可能需要一种自定义方式来添加新行,而不是使用数据网格。在这种情况下,一切都已经就绪,因为您只关心将新对象添加到您的集合中......您可能不太关心它是如何添加的。
      • 我查看了 DataTable RowChanged 事件,但它并没有在我的正确位置触发。但是 TableNewRow 事件确实在正确的时间触发(当新行生成时)。谢谢。
      • 在自定义行为这样的场景中,这句话是没用的。目前正在创建一种突出显示与选定行具有相同值(对于给定列)的行的行为,我不想在每一行上附加 Item 源。
      【解决方案4】:

      我添加这个是因为我刚刚花了将近 2 个小时试图弄清楚如何让 DataGrid 添加一个新行,当您绑定到一组视图模型并且您需要控制那些视图模型。

      所以设置是你有一个ObservableCollection&lt;MyViewModel&gt; 绑定到你的DataGrid 的ItemsSource。你需要在视图模型层自己创建MyViewModel

      这是 DataGrid 在自动添加行时的运行方式:

      1. 当它在底部创建空白行时,它会创建MyViewModel 的新实例,它将通过调用该类型的默认构造函数来绑定到该行。谁知道它为什么这样做,但如果MyViewModel 没有默认构造函数,它将无法显示该空白行。这可能是您卡住的地方,因为您没有默认构造函数,因为您需要自己创建对象。 不幸的是,你需要去添加一个。再次注意,如果元素类型是一个接口,这注定会失败。集合的元素类型必须是具有默认构造函数的具体类。
      2. 现在它一直等到用户开始编辑行,此时它开始正确添加。
      3. 它会引发AddingNewItem:您可以在此处拦截添加操作并切换默认构造函数创建的实例,它使用您自己的实例创建。 AddingNewItemEventArgs.NewItem 有一个设置器,您可以将当前项目换成自己的。

      【讨论】:

        【解决方案5】:

        我发现 DataGrid_InitializingNewItem 事件很有帮助,您可以在其中检查 e.NewItem 并根据其类型采取适当的措施。

        【讨论】:

          【解决方案6】:

          AddingNewItem 不同,DataGrid.LoadingRow Event(从 .Net 4.0 开始可用)将为通过ItemSource 绑定添加的项目触发。

          【讨论】:

            【解决方案7】:

            在您的 XAML 中,在您的 Window 标记中包含以下代码:

            xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
            xmlns:cmd="http://www.galasoft.ch/mvvmlight"
            

            接下来,在 DataGrid 元素中,添加以下触发器:

            <DataGrid ...>
            
              <i:Interaction.Triggers>
                    <i:EventTrigger EventName="LoadingRow">
                           <cmd:EventToCommand Command="{Binding LoadRowHandler}" 
                                                            PassEventArgsToCommand="True"/>
                     </i:EventTrigger>                        
               </i:Interaction.Triggers>
            
            </DataGrid>
            

            接下来,在您的 View Model 中,添加一个用于处理事件的命令:

            public RelayCommand<DataGridRowEventArgs> LoadRowHandler{ get; private set; }
            

            在构造函数内部,初始化命令:

            LoadRowHandler = new RelayCommand<DataGridRowEventArgs>(LoadingRowHandlerMethod);
            

            接下来,创建一个要放置逻辑的方法:

            private void LoadingRowHandlerMethod(DataGridRowEventArgs e)
            {
              //....
              //....
            }
            

            就是这样。现在,每当向 DataGrid 添加新行时,都会执行 LoadingRowHandlerMethod。

            希望对你有帮助。

            【讨论】:

              猜你喜欢
              • 2015-05-31
              • 1970-01-01
              • 1970-01-01
              • 2011-04-25
              • 2012-05-10
              • 1970-01-01
              • 1970-01-01
              • 2011-03-08
              • 2016-03-31
              相关资源
              最近更新 更多