【问题标题】:WPF DataGrid CellEditEnded eventWPF DataGrid CellEditEnded 事件
【发布时间】:2012-05-10 10:26:24
【问题描述】:

每次用户编辑我的 DataGrid 单元格的内容时,我都想知道。有 CellEditEnding 事件,但在对集合进行任何更改之前调用它,DataGrid 绑定到该事件。

我的数据网格绑定到ObservableCollection<Item>,其中Item 是一个类,从 WCF mex 端点自动生成。

每次用户提交对集合的更改时,最好的方法是什么。

更新

我尝试了 CollectionChanged 事件,当 Item 被修改时它不会被触发。

【问题讨论】:

    标签: c# wpf wcf data-binding datagrid


    【解决方案1】:

    您可以在数据网格的属性成员绑定上使用UpdateSourceTrigger=PropertyChanged。这将确保当 CellEditEnding 被触发时,更新已经反映在 observable 集合中。

    见下文

    <DataGrid SelectionMode="Single"
              AutoGenerateColumns="False"
              CanUserAddRows="False"
              ItemsSource="{Binding Path=Items}" // This is your ObservableCollection
              SelectedIndex="{Binding SelectedIndexStory}">
              <e:Interaction.Triggers>
                  <e:EventTrigger EventName="CellEditEnding">
                     <cmd:EventToCommand PassEventArgsToCommand="True" Command="{Binding EditStoryCommand}"/> // Mvvm light relay command
                   </e:EventTrigger>
              </e:Interaction.Triggers>
              <DataGrid.Columns>
                        <DataGridTextColumn Header="Description"
                            Binding="{Binding Name, UpdateSourceTrigger=PropertyChanged}" /> // Name is property on the object i.e Items.Name
              </DataGrid.Columns>
    
    </DataGrid>
    

    UpdateSourceTrigger = PropertyChanged 将在目标属性更改时立即更改属性源。

    这将允许您捕获对项目的编辑,因为将事件处理程序添加到可观察集合更改事件不会触发集合中对象的编辑。

    【讨论】:

    • 这在AutoGenerateColumns="True" 上如何工作?看起来为了让这成为可能,我们需要明确指定每一列。
    【解决方案2】:

    如果您需要知道已编辑的 DataGrid 项目是否属于特定集合,您可以在 DataGrid 的 RowEditEnding 事件中执行以下操作:

        private void dg_RowEditEnding(object sender, DataGridRowEditEndingEventArgs e)
        {
            // dg is the DataGrid in the view
            object o = dg.ItemContainerGenerator.ItemFromContainer(e.Row);
    
            // myColl is the observable collection
            if (myColl.Contains(o)) { /* item in the collection was updated! */  }
        }
    

    【讨论】:

      【解决方案3】:

      我改用了“CurrentCellChanged”。

          <DataGrid
              Grid.Row="1"
              HorizontalAlignment="Center"
              AutoGenerateColumns="True"
              AutoGeneratingColumn="OnAutoGeneratingColumn"
              ColumnWidth="auto"
              IsReadOnly="{Binding IsReadOnly}"
              ItemsSource="{Binding ItemsSource, UpdateSourceTrigger=PropertyChanged}">
              <b:Interaction.Triggers>
                  <!--  CellEditEnding  -->
                  <b:EventTrigger EventName="CurrentCellChanged">
                      <b:InvokeCommandAction Command="{Binding CellEditEndingCmd}" />
                  </b:EventTrigger>
              </b:Interaction.Triggers>
          </DataGrid>
      

      【讨论】:

        【解决方案4】:

        您应该在ObservableCollectionCollectionChanged 事件上添加一个事件处理程序。

        代码sn-p:

        _listObsComponents.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(ListCollectionChanged);
        
        // ...
        
        
            void ListCollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
            {
                /// Work on e.Action here (can be Add, Move, Replace...)
            }
        

        e.ActionReplace 时,这意味着列表中的一个对象已被替换。这个事件当然是在应用更改后触发的

        玩得开心!

        【讨论】:

        • 事实上,我在发布问题之前就是这样做的。用户修改集合时不会触发 CollectionChanged 事件
        • 这不是您的答案,但是,CollectionChanged 仅在以某种方式添加或删除项目时报告。很有可能,网格允许您在不真正改变集合本身的情况下修改项目,因此不会触发上述事件。
        • 糟糕,是的,这里有误解,CollectionChanged 将在完整的 Item 发生变化时被触发(即,您放置一个新的 Item() 而不是以前的)。如果你想捕捉每一个修改,你需要你的 Item 类来实现 INotifyPropertyChanged :)
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-04-22
        • 1970-01-01
        • 2016-03-31
        • 2015-05-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多