简体   繁体   English

MVVM ICommand绑定“更高”

[英]MVVM ICommand Binding “higher up”

I'm working on a shopping-cart like application as a way to practice the MVVM design pattern. 我正在研究类似购物车的应用程序,以此作为练习MVVM设计模式的一种方式。

I have a View whose ViewModel is pretty much just a ShoppingCart , and the ShoppingCart is primarily a list of Product s. 我有一个View,其ViewModel几乎只是一个ShoppingCart ,而ShoppingCart主要是Product的列表。

Right now, my view shows the Products in a GridView , which uses a DataTemplate to show the Name , Price , and a Remove button for each Product . 现在,我的视图在GridView中显示了Products ,该视图使用DataTemplate显示每个ProductNamePrice和一个Remove按钮。 The thing is, due to databinding, if I try databinding the Command attribute of the Remove button to a RemoveCommand property in my ViewModel, the code fails because it looks for RemoveCommand in the Product class instead of the ViewModel class. 事实是,由于数据绑定,如果我尝试将Remove按钮的Command属性数据绑定到ViewModel中的RemoveCommand属性,则代码将失败,因为它在Product类而不是ViewModel类中查找RemoveCommand

I highly doubt I want to break encapsulation and have the Product deal with removing itself from a ShoppingCart , but I can't seem to figure out the right way to tackle this issue. 我非常怀疑我想破坏封装并让Product处理将其从ShoppingCart中删除,但是我似乎无法找出解决此问题的正确方法。

Give your GridView a name and do a Command="{Binding ElementName=theGridView, Path=DataContext.RemoveCommand}" . 给您的GridView命名并执行Command="{Binding ElementName=theGridView, Path=DataContext.RemoveCommand}" You can also use a RelativeSource binding, although I think the former is faster. 您也可以使用RelativeSource绑定,尽管我认为前者更快。

You'll also want to pass the Product itself into the command handler so you know which one the user has clicked on, do that with CommandParameter="{Binding Path=.}" . 您还需要将产品本身传递到命令处理程序中,以便知道用户单击了哪个按钮,并使用CommandParameter="{Binding Path=.}" The RemoveCommand property should be declared to return type ICommand but should return a generic instance of RelayCommand ie: 应该声明RemoveCommand属性以返回ICommand类型,但是应该返回RelayCommand的通用实例,即:

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

use RelativeSource(ancestor) binding as a generic solution. 使用RelativeSource(ancestor)绑定作为一般解决方案。

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

So i hope the class which gridview has as a datacontext is holding this RemoveCommand command. 因此,我希望gridview作为数据上下文具有的类正在保存此RemoveCommand命令。 Or else in AncestorType put the control that has such datacontext which holds RemoveCommand command. 否则在AncestorType中放入具有此类datacontext的控件,其中包含RemoveCommand命令。

This was you can keep your encapsulation and binding will work too. 这是您可以保持封装和绑定也起作用的功能。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM