我希望每次 DataGrid 获得更多行或删除一些行时重新计算。我尝试使用该Loaded
事件,但只触发了一次。
我找到AddingNewItem
了,但是在添加之前就被解雇了。之后我需要做我的事情。
还有LayoutUpdated
,它可以工作,但我担心使用它是不明智的,因为它太频繁地触发我的目的。
我希望每次 DataGrid 获得更多行或删除一些行时重新计算。我尝试使用该Loaded
事件,但只触发了一次。
我找到AddingNewItem
了,但是在添加之前就被解雇了。之后我需要做我的事情。
还有LayoutUpdated
,它可以工作,但我担心使用它是不明智的,因为它太频繁地触发我的目的。
如果你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 PrismEventAggregator
或 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>()
怎么样DataGrid.LoadingRow(object sender, DataGridRowEventArgs e)
?
卸载也一样。
DataGrid.UnLoadingRow(object sender, DataGridRowEventArgs e)
?
您是否尝试过 MVVM 方法并绑定到 Observable 集合?
public ObservableCollection<Thing> Items{
get { return _items; }
set{ _items = value; RaisePropertyChanged("Items"); // Do additional processing here
}
}
所以你可以在不受 UI 约束的情况下观看项目的添加/删除?
如果您愿意,您可以RowUnloading
按照其他人在此处描述的路线走,但是请注意,每次一行失去焦点时也会触发此事件。
但是,通过玩耍,我发现当删除一行时SelectedItem
,网格的属性为空,而该CurrentItem
属性不为空,到目前为止,我只看到这个组合用于删除的行,(虽然我不能保证我有没有错过一个异国情调的情况......但是对于远离行的基本情况,我到目前为止还没有看到它)。
因此,何时可以使用以下代码仅过滤已删除的行:
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
}
如果您想使用 ObservableCollection 并获得有关添加或其他操作的通知,最好的方法是使用 INotifyCollectionChanged
var source = datagrid.ItemsSource as INotifyCollectionChanged;
因为,当你解包到 时ObservableCollection<MyClass>()
,你必须严格地写 MyClass (not ObservableCollection<ParentOfMyClass>
())
根据您要重新计算的“事物”,您可能会考虑使用 ScrollViewer.ScrollChanged 附加事件。这可以在 XAML 中设置如下:
<DataGrid
...
ScrollViewer.ScrollChanged="control_ScrollChanged">
ScrollChangedEventArgs对象具有有助于计算布局和滚动位置(Extent、Offset、Viewport)的各种属性。请注意,在使用默认虚拟化设置时,这些通常以行数/列数来衡量。
我一直在寻找解决方案,我找到了处理这个问题的完美事件,该事件称为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
}