C# 添加/删除行时,WPF DataGrid 是否会触发事件?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11293607/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Does WPF DataGrid fire an event when a row is added / removed?
提问by Tower
I wish to recalculate things everytime a DataGrid gets more rows or some are removed. I tried to use the Loadedevent, but that was fired only once.
我希望每次 DataGrid 获取更多行或删除一些行时重新计算。我尝试使用该Loaded事件,但只触发了一次。
I found AddingNewItem, but that is fired before it has been added. I need to do my stuff afterwards.
我找到了AddingNewItem,但是在添加之前就被解雇了。我需要做我的东西之后。
There's also LayoutUpdated, which works, but I'm afraid it's not wise to use it, because it fires way too often for my purposes.
还有LayoutUpdated, 有效,但恐怕使用它是不明智的,因为它太频繁地触发我的目的。
采纳答案by Rachel
If your DataGridis bound to something, I think of two ways of doing this.
如果您DataGrid绑定到某些东西,我会想到两种方法来做到这一点。
You could try getting the DataGrid.ItemsSourcecollection, and subscribing to its CollectionChangedevent. This will only work if you know what type of collection it is in the first place.
您可以尝试获取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
}
The other solution would be to use an Event System such as Microsoft Prism's EventAggregatoror MVVM Light's Messenger. This means your ViewModelwould broadcast a DataCollectionChangedevent message anytime the bound collection changes, and your Viewwould subscribe to receive these messages and execute your code anytime they occur.
另一种解决方案是使用事件系统,例如 Microsoft PrismEventAggregator或 MVVM Light 的Messenger. 这意味着您ViewModel将DataCollectionChanged在绑定集合更改时广播事件消息,并且您View将订阅接收这些消息并在它们发生时执行您的代码。
Using EventAggregator
使用 EventAggregator
// Subscribe
eventAggregator.GetEvent<CollectionChangedMessage>().Subscribe(DoWork);
// Broadcast
eventAggregator.GetEvent<CollectionChangedMessage>().Publish();
Using Messenger
使用 Messenger
//Subscribe
Messenger.Default.Register<CollectionChangedMessage>(DoWork);
// Broadcast
Messenger.Default.Send<CollectionChangedMessage>()
回答by Nikhil Agrawal
How about DataGrid.LoadingRow(object sender, DataGridRowEventArgs e)?
怎么样DataGrid.LoadingRow(object sender, DataGridRowEventArgs e)?
Same for Unloading.
卸载相同。
DataGrid.UnLoadingRow(object sender, DataGridRowEventArgs e)?
DataGrid.UnLoadingRow(object sender, DataGridRowEventArgs e)?
回答by Josh
Have you tried an MVVM approach and binding to an Observable collection?
您是否尝试过 MVVM 方法并绑定到 Observable 集合?
public ObservableCollection<Thing> Items{
get { return _items; }
set{ _items = value; RaisePropertyChanged("Items"); // Do additional processing here
}
}
So you can watch the add / remove of items without being tied to the UI?
所以你可以在不绑定到 UI 的情况下观看项目的添加/删除?
回答by Smagin Alexey
If you want use ObservableCollection and get notification about add or another operation, the best way use INotifyCollectionChanged
如果您想使用 ObservableCollection 并获得有关添加或其他操作的通知,最好的方法是使用 INotifyCollectionChanged
var source = datagrid.ItemsSource as INotifyCollectionChanged;
Because, when you will unwrap to ObservableCollection<MyClass>(), you must write strogly MyClass (not ObservableCollection<ParentOfMyClass>())
因为,当你解包到 时ObservableCollection<MyClass>(),你必须严肃地写 MyClass (而不是ObservableCollection<ParentOfMyClass>())
回答by Matt
Depending on what "things" you want to recalculate, you might consider using the ScrollViewer.ScrollChanged attached event. This can be set in XAML as follows:
根据您要重新计算的“事物”,您可以考虑使用 ScrollViewer.ScrollChanged 附加事件。这可以在 XAML 中设置如下:
<DataGrid
...
ScrollViewer.ScrollChanged="control_ScrollChanged">
The ScrollChangedEventArgsobject has various properties that can be helpful for computing layout and scroll position (Extent, Offset, Viewport). Note that these are typically measured in numbers of rows/columns when using the default virtualization settings.
所述ScrollChangedEventArgs对象具有各种性质,可以是用于计算布局和滚动位置有用的(程度上抵消,视口)。请注意,当使用默认虚拟化设置时,这些通常以行/列数来衡量。
回答by Charaf
I was looking for solution to this and I have found the perfect event to handle this, the event is called UnloadingRow
我一直在寻找解决方案,我找到了处理此问题的完美事件,该事件称为UnloadingRow
<DataGrid ....
UnloadingRow="DataGrid_UnloadingRow">
...
</DataGrid>
In your C# code u get this
在你的 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
}
回答by yoel halb
If you want you can go down the RowUnloadingroute as others have described here, however note that this event fires also every time a row is losing focus.
如果您愿意,您可以RowUnloading按照其他人在此处描述的路线走下去,但请注意,每次行失去焦点时也会触发此事件。
However by playing around I found that when a row is removed the SelectedItemproperty of the grid is null while the CurrentItemproperty is not null, and so far I have seen this combination only for a deleted row, (although I can't guarantee that I have not missed an exotic situation... however for the basic situations of moving away from the row I have not seen it so far).
然而,通过玩弄我发现当一行被删除SelectedItem时,网格的CurrentItem属性为空,而该属性不为空,到目前为止我只看到了删除行的这种组合,(虽然我不能保证我有没有错过异国情调的情况......但是对于远离行的基本情况,我到目前为止还没有见过)。
So when can use the following code to filter for deleted rows only:
所以什么时候可以使用下面的代码来过滤删除的行:
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
}

