【发布时间】:2021-11-15 03:58:41
【问题描述】:
我有这个有四个主要视图的 WPF 应用程序。其中一个视图,我们称之为“OrdersView”,有一个包含订单的 DataGrid。为此,DataContext 是一个 ViewModel,即“OrdersViewModel”,当然,它实现了 INotifyPropertyChanged。网格的每一行都有一个按钮来查看订单的详细信息。此按钮通过窗口服务打开一个新窗口,允许用户通过处理订单、添加更多项目或删除订单来更新订单。该窗口包含一个名为“OrderDetailsView”的用户控件,它当然有一个“OrderDetailsViewModel”作为 DataContext。我对“编辑订单”和“处理订单”功能没有任何问题。问题是“删除订单”。此按钮绑定到 ViewModel 中的命令,该命令引发事件并将订单 Id 发送到应用程序主窗口中的侦听器,然后主窗口将此 Id 传递给“OrdersViewModel”中具有查找功能的方法在 ObservableCollection 中排序并将其删除。 该项目已删除,我在调试器中看到了 Collection 的变化,但是当“OrderDetailsView”关闭时,Orders DataGrid 仍然有血腥的订单,只有当我导航到不同的视图并返回时才会刷新它。 我试图将 RaisePropertyChanged 方法放在集合的 setter 中,在 delete 方法的末尾,属性名称为 Orders 并且不起作用。
数据网格开始如下:
<DataGrid ItemsSource="{Binding Path=Orders}"
Style="{DynamicResource DataGridStyle}">
ViewDetails 按钮是:
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button x:Name="BtnOrderDetails"
Content="View"
Margin="1"
Command="{Binding DataContext.SeeOrderDetailsCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}"
CommandParameter="{Binding}" />
</DataTemplate>
OrdersViewModel 类似于:
public class OrdersViewModel : ViewModelBase
{
private ObservableCollection<Order> _orders;
public OrdersViewModel(List<Order> orders)
{
Orders = new ObservableCollection<Order>(orders);
}
public ObservableCollection<Order> Orders
{
get => _orders;
set
{
_orders = value;
RaisePropertyChanged();
}
}
public void DeleteOrder(int id)
{
Orders.Remove(Orders
.FirstOrDefault(order => order.Id.Equals(id)));
RaisePropertyChanged(nameof(Orders));
}
}
“查看详细信息”按钮会将您带到一个新窗口,该窗口包含“OrderDetailsView”并具有如下按钮:
<Button x:Name="DeleteOrder"
Content="Delete order"
Grid.Row="2"
Margin="10,0,0,10"
Style="{StaticResource DeleteOrderButton}"
Command="{Binding DeleteOrderCommand}"/>
在此视图的视图模型中,我有以下内容:
public DelegateCommand DeleteOrderCommand { get; private set; }
在构造函数中:
DeleteOrderCommand = new DelegateCommand(DeleteOrder, () => CanDelete);
该方法引发了一个事件(你是这么说的吗?):
private void DeleteOrder()
{
DeleteOrderRequested(Order.Id);
CloseWindow();
}
public event Action<int> DeleteOrderRequested = delegate { };
我的主窗口是传达不同视图模型的东西,它捕获了这个事件:
private void OnDeleteOrderRequested(int id)
{
OrdersViewModel.DeleteOrder(id);
}
我知道,它的功能是一个愚蠢的复杂应用程序,对吧?
为什么,为什么,为什么视图没有收到有关项目已被删除的通知???
有人可以帮忙吗?或者至少告诉我在哪里继续寻找?
谢谢大家!
【问题讨论】:
-
很难理解你的逻辑是如何工作的,因为你选择只发布松散的代码 sn-ps。您应该检查是否调用了命令并监听事件并在正确的实例上调用 delete - 确保您仅使用单个 OrdersViewModel 实例。您定义事件委托的方式非常不同寻常。您应该改用
Eventhandler<TEventArgs>。但更重要的是考虑让您的 OrdersViewModel 为当前选定的订单公开 OrdersDetailsViewModel。这可以显着简化逻辑并很有可能解决问题。 -
非常感谢您的回复。完全同意,就是代码太多了,就是觉得不合适贴200行代码来解释viewModel的作用。我不知道如何使用你提到的 eventHandler,不过我会调查的,保证。无论如何,我发现了问题。与启动时 currentViewModel 的分配有关。在这里解释太长了。再次感谢。
标签: c# wpf mvvm observablecollection