MVVM Master Detail 与 WPF TreeView
MVVM Master Detail with WPF TreeView
我有以下情况:
观看次数:
- EbayCategoriesView(带有 TreeView)
- MaintainEbayCategoryView(带有类别详细信息字段)
视图模型:
- EbayAllCategoriesViewModel(带有名为 EbayCategories 的 EbayCategoryViewModel 的 ObservableCollection)。
- EbayCategoryViewModel(具有类别属性)
EbayCategoryViewModel 有一个 public 属性,这是一个名为 ChildrenCategories 的列表。 TreeView 绑定到 ObservableCollection,TreeView 的每个节点都是一个超链接。
我希望当单击超链接时,系统会打开 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 的 LoadCategoryDetails() 方法中,我没有任何已单击的 EbayCategoryViewModel 树节点的引用(TreeView 中的 SelectedItem 不是 public,并且我也不确定它是否包含被点击的元素...)。
即使我找到了一些解决方法,我也想了解解决我的问题的正确方法是什么,尊重 MVVM 模式。
因为我已经拥有 EbayCategoryViewModel 中的所有类别字段,所以我将能够访问当前被单击的 EbayCategoryViewModel 对象,而无需再次访问我的数据源。
提前感谢您的任何建议。
为什么不将 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
设置为 return DataContext,即 EbayCategoryViewModel CommandParameter="{Binding}"
的实例
@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 加载 其 详细信息,因此我认为没有必要为命令提供参数。在您使用它的任何情况下,您实际上都在说 "Dear category, please load your details, and by the way, this is who you are"。这种冗余的必要性是由于您的视图模型中相当随意的实现细节。它不是破坏性的,但它需要您的 类 的消费者付出额外的努力,而无需添加任何东西。
如果它是对父级的命令,语义将是 "tell some particular child to load its details",然后参数将是告诉它哪个子级的正确方法。这就是父类 LoadCategoryDetails(ecvm)
方法的确切语义,因为 Nitin 和我都建议您重写它。
Nitin 的答案是常规的、高质量的专业 WPF 编程。从任何标准来看都是正确的。但是我的 偏好 是在 EbayCategoryViewModel
上从该命令调用该方法时隐藏该参数的传递。这并不是一个足够强烈的偏好来证明我刚刚倾倒在它上面的散文数量是合理的,但我想我会解释为什么我添加了一个 unnecessary (lolseewhatididthere?) 第二个答案这个问题。
我有以下情况:
观看次数:
- EbayCategoriesView(带有 TreeView)
- MaintainEbayCategoryView(带有类别详细信息字段)
视图模型:
- EbayAllCategoriesViewModel(带有名为 EbayCategories 的 EbayCategoryViewModel 的 ObservableCollection)。
- EbayCategoryViewModel(具有类别属性)
EbayCategoryViewModel 有一个 public 属性,这是一个名为 ChildrenCategories 的列表。 TreeView 绑定到 ObservableCollection,TreeView 的每个节点都是一个超链接。 我希望当单击超链接时,系统会打开 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 的 LoadCategoryDetails() 方法中,我没有任何已单击的 EbayCategoryViewModel 树节点的引用(TreeView 中的 SelectedItem 不是 public,并且我也不确定它是否包含被点击的元素...)。
即使我找到了一些解决方法,我也想了解解决我的问题的正确方法是什么,尊重 MVVM 模式。 因为我已经拥有 EbayCategoryViewModel 中的所有类别字段,所以我将能够访问当前被单击的 EbayCategoryViewModel 对象,而无需再次访问我的数据源。
提前感谢您的任何建议。
为什么不将 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
设置为 return DataContext,即 EbayCategoryViewModel CommandParameter="{Binding}"
@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 加载 其 详细信息,因此我认为没有必要为命令提供参数。在您使用它的任何情况下,您实际上都在说 "Dear category, please load your details, and by the way, this is who you are"。这种冗余的必要性是由于您的视图模型中相当随意的实现细节。它不是破坏性的,但它需要您的 类 的消费者付出额外的努力,而无需添加任何东西。
如果它是对父级的命令,语义将是 "tell some particular child to load its details",然后参数将是告诉它哪个子级的正确方法。这就是父类 LoadCategoryDetails(ecvm)
方法的确切语义,因为 Nitin 和我都建议您重写它。
Nitin 的答案是常规的、高质量的专业 WPF 编程。从任何标准来看都是正确的。但是我的 偏好 是在 EbayCategoryViewModel
上从该命令调用该方法时隐藏该参数的传递。这并不是一个足够强烈的偏好来证明我刚刚倾倒在它上面的散文数量是合理的,但我想我会解释为什么我添加了一个 unnecessary (lolseewhatididthere?) 第二个答案这个问题。