C# WPF DataGrid在添加/删除行时是否触发事件?
每当DataGrid获得更多行或删除一些行时,我都希望重新计算。我试图使用C# WPF DataGrid在添加/删除行时是否触发事件?,c#,.net,wpf,C#,.net,Wpf,每当DataGrid获得更多行或删除一些行时,我都希望重新计算。我试图使用Loaded事件,但只触发了一次 我找到了,但在添加之前就被触发了。之后我需要做我的事情 还有LayoutUpdated,它很有效,但是我担心使用它是不明智的,因为它为我的目的太频繁了。关于DataGrid.LoadingRow(objectsender,DataGridRowEventArgs e) 卸货也一样 DataGrid.UnloadingGrow(对象发送方,DataGridRowEventArgs e)?如果
Loaded
事件,但只触发了一次
我找到了,但在添加之前就被触发了。之后我需要做我的事情
还有
LayoutUpdated
,它很有效,但是我担心使用它是不明智的,因为它为我的目的太频繁了。关于DataGrid.LoadingRow(objectsender,DataGridRowEventArgs e)
卸货也一样
DataGrid.UnloadingGrow(对象发送方,DataGridRowEventArgs e)
?如果您的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
}
使用Messenger
//Subscribe
Messenger.Default.Register<CollectionChangedMessage>(DoWork);
// Broadcast
Messenger.Default.Send<CollectionChangedMessage>()
//订阅
Messenger.Default.Register(DoWork);
//广播
Messenger.Default.Send()
您是否尝试过MVVM方法并绑定到可观察的集合
public ObservableCollection<Thing> Items{
get { return _items; }
set{ _items = value; RaisePropertyChanged("Items"); // Do additional processing here
}
}
公共可观察收集项目{
获取{return\u items;}
设置{u items=value;RaisePropertyChanged(“items”);//在此处执行其他处理
}
}
因此,您可以在不绑定到UI的情况下查看项目的添加/删除?如果您希望使用ObservableCollection并获得有关添加或其他操作的通知,请更改使用InotifyCollection的最佳方式
var source = datagrid.ItemsSource as INotifyCollectionChanged;
因为,当你打开到
,这取决于你想重新计算什么“东西”,你可以考虑使用ScLabVIEWR.ScRelchange附加事件。这可以在XAML中设置,如下所示:
<DataGrid
...
ScrollViewer.ScrollChanged="control_ScrollChanged">
对象具有各种属性,这些属性有助于计算布局和滚动位置(范围、偏移、视口)。请注意,在使用默认虚拟化设置时,这些通常是以行/列的数量来衡量的。我一直在寻找解决方案,我发现了处理此问题的完美事件,该事件称为UnloadingRow
如果您愿意,您可以像其他人在这里所描述的那样沿着
行卸载
路线,但是请注意,每次行失去焦点时,也会触发此事件
然而,通过玩游戏,我发现当删除一行时,网格的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
}
您可以在不触发此事件的情况下向
DataGrid
的数据源添加新行。此事件与可视行(DataGridRow
对象)相关而不是数据源中的行。在这种情况下,将您的datagrid绑定到ObservableCollection
。只需从行中移开卸载就可以触发,而不仅仅是删除。虽然这是处理应用程序逻辑的集合更改事件的正确方法,但我认为OP是基于某些原因询问视图的集合更改事件中的注释我试图在代码中实现这一点,添加notify collection changed事件处理程序,但我的sourceCollection始终等于“null”。我没有ViewModelBase作为ObservableCollection模板的可用类…我使用的是VS 20113(express)绑定到SQLServer2014 express数据库和WPF应用程序。我无法找到缺少的“使用”指令会给我ViewModelBase…我做错了什么?谢谢Paul@PaulGibsonViewModelBase
是一个自定义类,我通常在我所有的ViewModels上实现。在您的情况下,只需将其转换为ItemsSource中的任何类型的项即可。感谢您的解释,这是我在谷歌搜索后得出的结论。因此我e尝试了数据表的类以及行类(通用DataRow和MyDataRow的特定类)sourceCollection的yeild null和yeild null…我在这里发布了一个问题,其中包含代码块…我确信我做了一些简单的错误,但找不到正确的组合。我尝试了第二种方法,Prism中的EventAggregator。在这种情况下,当向DataGrid添加新行时,焦点已经设置为下一个元素。当我单击该行时,事件会触发,因为此时集合确实发生了变化。当CanUserAddRows设置为true时,向datagrid添加新行时是否会立即触发事件?@Vishal我个人不会为此使用CanUserAddRows。我会为用户提供“添加”按钮,该按钮将记录添加到源集合中,或向源集合提供空白项,并且每当填充该空白项时,添加一个新的空白项以替换“新”项就我个人而言,我更喜欢第一种解决方案,因为我发现网格中多余的空行经常会让用户感到困惑,并且更难验证,因为我总是要检查项目是否是“新的”item当任何行以可视方式卸载时,而不是以逻辑方式卸载时,此操作有效;因此,它将在任何行卸载时触发,如果进行虚拟化,则无论该项在操作之前是否已存在,都可能发生这种情况。理想的行为是仅当从基础集合中添加或删除项时触发。卸载只需从该行不只是用于删除
<DataGrid ....
UnloadingRow="DataGrid_UnloadingRow">
...
</DataGrid>
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
}
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
}