【问题标题】:MVVM ICommand Binding "higher up"MVVM ICommand 绑定“更高”
【发布时间】:2016-04-23 06:02:04
【问题描述】:

我正在开发一个类似购物车的应用程序,以此来实践 MVVM 设计模式。

我有一个 View,它的 ViewModel 几乎只是一个 ShoppingCart,而 ShoppingCart 主要是一个 Product 列表。 p>

现在,我的视图在 GridView 中显示 Products,它使用 DataTemplate 来显示 NamePrice,每个产品都有一个删除按钮。问题是,由于数据绑定,如果我尝试将 Remove 按钮的 Command 属性数据绑定到 ViewModel 中的 RemoveCommand 属性,代码会失败,因为它会查找 RemoveCommandProduct 类而不是 ViewModel 类中。

我非常怀疑我是否想打破封装并让 Product 处理将自己从 ShoppingCart 中删除,但我似乎无法找到正确的方法解决这个问题。

【问题讨论】:

  • 我们需要查看您的 ViewModel、View 和 Product 类。
  • 虽然如果我遇到语法障碍,这是一个好主意,但我真的在寻找一个通用的、基于概念的解决方案,而不是让别人吐出代码让我复制。这就是为什么我暂时不发布 XAML/C# 的原因。

标签: c# mvvm data-binding uwp icommand


【解决方案1】:

为您的 GridView 命名并执行 Command="{Binding ElementName=theGridView, Path=DataContext.RemoveCommand}"。您也可以使用 RelativeSource 绑定,尽管我认为前者更快。

您还需要将产品本身传递给命令处理程序,以便知道用户单击了哪个,请使用CommandParameter="{Binding Path=.}" 执行此操作。 RemoveCommand 属性应声明为返回类型 ICommand 但应返回 RelayCommand 的通用实例,即:

public ICommand RemoveCommand { get { return new RelayCommand<Product>(OnRemove); } }
private void OnRemove(Product product)
{
    // remove it here
}

【讨论】:

  • 是的!听起来我必须修改我的 ICommand 实现,因为现在我使用的是 Action 类型,它不允许使用 CommandParameters。但我认为如果我确实使用 CommandParameter 会更流畅,因为那时我不必绑定到 ViewModel 中的 CurrentSelectedProduct。
  • @afding 这是更好的解决方案。除了“路径=。”是多余的。 {绑定}就足够了。使用ElementName 比使用RelativeSource 绑定更好。
【解决方案2】:

使用 RelativeSource(ancestor) 绑定作为通用解决方案。

   Command="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type GridView}}, Path=DataContext.RemoveCommand}"

所以我希望 gridview 作为数据上下文的类持有这个 RemoveCommand 命令。否则在 AncestorType 中放置具有此类数据上下文的控件,该控件包含 RemoveCommand 命令。

这是你可以保持你的封装和绑定也可以工作。

【讨论】:

  • RemoveCommand 在视图模型(GridView 的 DataContext)中定义,而不是在 GridView 本身中。您的意思可能是“Path=DataContext.RemoveCommand”
猜你喜欢
  • 1970-01-01
  • 2013-08-05
  • 2011-04-16
  • 1970-01-01
  • 2011-05-09
  • 2019-03-04
  • 2010-11-30
  • 2011-01-17
  • 1970-01-01
相关资源
最近更新 更多