使用WPF TreeView的MVVM主细节

时间:2016-04-22 14:37:18

标签: wpf mvvm treeview relaycommand

我有以下情况:

查看:

  • EbayCategoriesView(使用TreeView)
  • MaintainEbayCategoryView(包含类别明细字段)

的ViewModels:

  • EbayAllCategoriesViewModel(使用名为EbayCategories的EbayCategoryViewModel的ObservableCollection)。
  • EbayCategoryViewModel(带类别属性)

EbayCategoryViewModel有一个公共属性,即名为ChildrenCategories的List。 TreeView绑定到ObservableCollection,TreeView的每个节点都是HyperLink。 我想在单击超链接时,系统会打开MaintainEbayCategoryView并使用EbayCategoryViewModel数据加载它。

我正在使用MVVM模式; EbayCategoryViewModel接受构造函数中的输入ICommand参数。当我在EbayAllCategoriesViewModel中填充ObservableCollection时,我为集合的每个元素创建一个新的RelayCommand并传递应该执行的函数:

hierarchyList.Add(new EbayCategoryViewModel(
                    item.EbayCategoryName, 
                    item.EbayCategoryID, 
                    FillRecursive(flatList, item.EbayCategoryID, item.EbayCategoryName),
                    parentCategoryName,
                    item.EbayOrder,
                    new RelayCommand(cmd => this.LoadCategoryDetails())
                        ));

我现在的问题是,在EbayAllCategoriesViewModel的LoadCategoryDe​​tails()方法中,我没有任何已被点击的EbayCategoryViewModel树节点的引用(TreeView中的SelectedItem不公开,而且我也不确定它包含被点击的元素...)。

即使我找到了一些解决方法,我想了解什么是解决我的问题的正确方法,尊重MVVM模式。 由于我已经拥有EbayCategoryViewModel中的所有类别字段,因此我可以访问被点击的当前EbayCategoryViewModel对象,而无需再次访问我的数据源。

提前感谢任何建议。

2 个答案:

答案 0 :(得分:2)

为什么不在命令处理程序中将EbayCategoryViewModel实例作为参数传递。通过这种方式,您将拥有VM的实例。

hierarchyList.Add(new EbayCategoryViewModel(
                    item.EbayCategoryName, 
                    item.EbayCategoryID, 
                    FillRecursive(flatList, item.EbayCategoryID, item.EbayCategoryName),
                    parentCategoryName,
                    item.EbayOrder,
                    new RelayCommand(param=> this.LoadCategoryDetails(param))
                        ));

并且绑定命令的位置可以设置CommandParameter以返回DataContext,即EbayCategoryViewModel的实例CommandParameter="{Binding}"

答案 1 :(得分:2)

@Nitin的回答是正确的,但这是另一种更简单的方法:

var ecvm = new EbayCategoryViewModel(
        item.EbayCategoryName, 
        item.EbayCategoryID, 
        FillRecursive(flatList, item.EbayCategoryID, item.EbayCategoryName),
        parentCategoryName,
        item.EbayOrder,
        null);

//  Guessing at the name of your command property here
ecvm.LoadCategoryDetailsCommand 
    = new RelayCommand(cmd => this.LoadCategoryDetails(ecvm));

hierarchyList.Add(ecvm);

其他地方......

public void LoadCategoryDetails(EbayCategoryViewModel vm)
{
    //  Do stuff
}

我个人个人更喜欢我对Nitin的回答,因为这个特定命令的语义:它告诉一个类别来加载它自己的细节。我不认为在那种情况下你会告诉A类告诉B类加载的详细信息,所以我不认为有必要给命令一个参数。在您使用它的每种情况下,您实际上在说#34;亲爱的类别,请加载您的详细信息,顺便说一句,这就是您的身份"。冗余的必要性是由于viewmodel中相当任意的实现细节。它不具有破坏性,但它需要您班级消费者的额外努力,而无需添加任何内容。

如果它是父母的命令,语义将是"告诉某个特定的孩子加载其细节",然后参数将是告诉它哪个孩子的正确方法。这就是父母LoadCategoryDetails(ecvm)方法的确切语义,因为Nitin和我都建议你重写它。

Nitin的答案是传统的,高质量的专业WPF编程。任何标准都是正确的。但是我的首选项是在EbayCategoryViewModel上从该命令调用该方法时隐藏该参数的传递。它并不是一个足够强烈的偏好来证明我刚刚抛弃的散文的数量,但我想我会解释为什么我添加了不必要的(lolseewhatididthere) ?)这个问题的第二个答案。