添加/删除行时,WPF DataGrid是否会触发事件?

时间:2012-07-02 12:21:30

标签: c# .net wpf

每当DataGrid获取更多行或删除一些行时,我希望重新计算内容。我尝试使用Loaded事件,但只触发了一次。

我找到了AddingNewItem,但在添加之前就已经解雇了。我之后需要做的事情

还有LayoutUpdated,它有效,但我担心使用它并不明智,因为它经常用于我的目的。

7 个答案:

答案 0 :(得分:9)

如果你的DataGrid被绑定了,我想到了两种方法。

您可以尝试获取DataGrid.ItemsSource集合,并订阅其CollectionChanged事件。这只有在你知道它最初是什么类型的集合时才有效。

// Be warned that the `Loaded` event runs anytime the window loads into view,
// so you will probably want to include an Unloaded event that detaches the
// collection
private void DataGrid_Loaded(object sender, RoutedEventArgs e)
{
    var dg = (DataGrid)sender;
    if (dg == null || dg.ItemsSource == null) return;

    var sourceCollection = dg.ItemsSource as ObservableCollection<ViewModelBase>;
    if (sourceCollection == null) return;

    sourceCollection .CollectionChanged += 
        new NotifyCollectionChangedEventHandler(DataGrid_CollectionChanged);
}

void DataGrid_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
    // Execute your logic here
}

另一种解决方案是使用事件系统,例如Microsoft Prism的EventAggregator或MVVM Light Messenger。这意味着您的ViewModel会在绑定集合发生更改时广播DataCollectionChanged事件消息,并且您的View会订阅接收这些消息并在任何时候执行您的代码。

使用EventAggregator

// Subscribe
eventAggregator.GetEvent<CollectionChangedMessage>().Subscribe(DoWork);

// Broadcast
eventAggregator.GetEvent<CollectionChangedMessage>().Publish();

使用Messenger

//Subscribe
Messenger.Default.Register<CollectionChangedMessage>(DoWork);

// Broadcast
Messenger.Default.Send<CollectionChangedMessage>()

答案 1 :(得分:2)

DataGrid.LoadingRow(object sender, DataGridRowEventArgs e)怎么样?

卸载相同。

DataGrid.UnLoadingRow(object sender, DataGridRowEventArgs e)

答案 2 :(得分:2)

您是否尝试过MVVM方法并绑定到Observable集合?

public ObservableCollection<Thing> Items{
get { return _items; }
set{ _items = value; RaisePropertyChanged("Items");  // Do additional processing here 
}
}

因此,您可以观看添加/删除项目而不必与UI绑定?

答案 3 :(得分:0)

如果你想使用ObservableCollection并获得有关添加或其他操作的通知,最好的方法是使用INotifyCollectionChanged

var source = datagrid.ItemsSource as INotifyCollectionChanged;

因为,当您要打开ObservableCollection<MyClass>()时,您必须写出极具吸引力的MyClass(不是ObservableCollection<ParentOfMyClass>())

答案 4 :(得分:0)

如果您愿意,可以像其他人在此处描述的那样沿着RowUnloading路线前进,但请注意,每当一行失去焦点时,此事件也会触发。

然而,通过四处游戏,我发现当删除一行时,网格的SelectedItem属性为null,而CurrentItem属性不为null,到目前为止我只看到了这个组合已删除的行,(虽然我不能保证我没有错过异国情况......但是对于离开行的基本情况我到目前为止还没有看到过。)

因此,何时可以使用以下代码仅过滤已删除的行:

private void CategoriesGrid_UnloadingRow(object sender, DataGridRowEventArgs e)
{     
        if (((DataGrid)sender).SelectedItem != null || ((DataGrid)sender).CurrentItem == null)
        {
            return;
        }

        // The rest of your code goes here
}

答案 5 :(得分:-1)

取决于&#34;事物&#34;如果要重新计算,可以考虑使用ScrollViewer.ScrollChanged附加事件。这可以在XAML中设置如下:

<DataGrid
...
ScrollViewer.ScrollChanged="control_ScrollChanged">

ScrollChangedEventArgs对象具有各种属性,可用于计算布局和滚动位置(范围,偏移,视口)。请注意,使用默认虚拟化设置时,这些通常以行/列数量来衡量。

答案 6 :(得分:-1)

我一直在寻找解决方案,我找到了完美的事件来处理这个事件,这个事件叫做 UnloadingRow

<DataGrid ....
    UnloadingRow="DataGrid_UnloadingRow">
 ...
</DataGrid>

在你的C#代码中,你得到这个

private void ProductsDataGrid_UnloadingRow(object sender, DataGridRowEventArgs e)
{
   MyObject obj = (MyObject)e.Row.Item; // get the deleted item to handle it
   // Rest of your code ...
   // For example : deleting the object from DB using entityframework

}