6

我现在为一个简单的任务苦苦挣扎了大约 14 天:在数据库中,我有硬件类别的定义。例如 :

  1. 硬盘
    • 内部的
    • 外部的
    • 闪光

此列表在数据库中定义如下:

    [ID - ParrentID - Name] : 1 - 0 - HDD, 2 - 1 - Internal, 3 - 1 - External, 4 - 1 - Flash.        

通过实体框架,我将这些行放入我的应用程序中。然后从这个平面数据中创建结构化对象,即我的 DataModel。该模型定义如下:

public class Category
{
   private int _id = -1;
   private string _name = "";
   private List<Category> _subCategories = null;
// property getters and setters, constructors, and bool HasSubCategories
}  

现在,我根据这些创建了名为SubCategoryViewModel的 ViewModel ,它绑定了我的 TreeView。因此,我可以在树视图中查看我的类别,并使用我定义和维护的层次结构。这工作得很好。在SubCategoryViewModel中,通过MouseDoubleClick 的附加行为定义了一个命令,该命令也绑定到 TreeView。因此,当用户双击 Item 时,在SubViewCategoryModel中定义的方法将执行特定代码。SubCategoryViewModel列表 嵌套在HWDocumentViewModel中这是我的窗口的主要 ViewModel。我现在需要的很明显:当用户双击 TreeView 中的项目时,我需要从数据库中加载项目并在 ListView 中显示它们。我的观点是,在HWDocumentViewModel中,我需要定义一个 Items 集合并将它们相应地加载到 ListView 中的选定类别。但是,我不知道如何从 SubCategoryViewModel 对 HWDocumentViewModel 执行方法。因为:TreeView 绑定到SubCategoryViewModel项目列表,所以当 DoubleClick 发生时,SubCategoryViewModel上的方法被执行。我正在寻找一种方法,如何在主 ViewModel (HWDocumentViewModel) 上执行方法。

我尝试了这种方法:
我创建了一个属性:public static SubCategoryViewModel SelectedCategoryon HWDocumentViewModel。发生双击时,我将此属性从 SubCategoryViewModel 设置为this. 因此,在这个属性中是执行双击事件委托的对象。太好了,现在我在 HWDocumentView 模型中有一个用户选择的对象。
所以,我需要将项目加载到 ListView。但是,我会从SubCategoryViewModel中的方法加载它们吗?我不这么认为。相反,我应该通过为它们创建一个 ViewModel 并将其绑定到 ListView 来从主视图模型加载它们,对吗?但是,如何从 SubCategoryViewModel 调用 HWDocumentViewModel 中的方法?我应该在可以从 SubCategoryViewModel 访问的 HWDocumentViewModel 上编写一个静态方法吗?
或者有没有办法,如何从 SubCategoryViewModel 调用在 HWDocumentViewModel 上定义的命令?

或者一般来说,我是否采取了正确的方法在 WPF 中创建类似仓库的应用程序?

非常感谢。

编辑:我的 TreeView 的 XAML 如下所示:

<TreeView x:Name="tvCategories" Background="White" ItemsSource="{Binding Categories}">
                    <TreeView.ItemContainerStyle>
                        <Style TargetType="{x:Type TreeViewItem}">
                            <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
                            <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
                            <Setter Property="FontWeight" Value="Normal" />
                            <Setter Property="behaviors:MouseDoubleClick.Command"  Value="{Binding MouseDoubleClickCommand}" />
                            <Setter Property="behaviors:MouseDoubleClick.CommandParameter" Value="{Binding}" />
                            <Style.Triggers>
                                <Trigger Property="IsSelected" Value="True">
                                    <Setter Property="FontWeight" Value="Bold" />
                                </Trigger>
                            </Style.Triggers>
                        </Style>
                    </TreeView.ItemContainerStyle>
                    <TreeView.Resources>
                        <HierarchicalDataTemplate DataType="{x:Type localvm:SubCategoryViewModel}" ItemsSource="{Binding Children}">
                            <StackPanel Orientation="Horizontal">
                                <TextBlock Text="{Binding CategoryName}" />
                            </StackPanel>
                        </HierarchicalDataTemplate>
                    </TreeView.Resources>

                </TreeView>
4

2 回答 2

5

我不确定我是否看到了问题。You have a tree of subcategories and when one is selected, the appropriate SubCategoryViewModelsets itself as SelectedCategoryon the main HWDocumentViewModel. 这似乎是一个合理的方法。

那么为什么需要调用命令呢?为什么不能只加载新列表以HWDocumentViewModel响应其SelectedCategory属性的更改(即在 setter 中)?

如果您确实必须使用命令来调用加载,那么只需HWDocumentViewModel在 each 中保留对 main 的引用,然后SubCategoryViewModel使用简单的命令调用该命令:

_mainViewModel.LoadCategoryCommand.Execute();
于 2012-04-09T15:10:00.483 回答
3

使用 MVVM 并尝试在 View 和 ViewModel 之间或 ViewModel 之间进行通信,发布者/订阅者设置运行良好,或者像 MVVMLight 或 Prism 中的消息传递范例。我在此处发布了有关 MVVM Light 消息设置的答案

在消息中,您可以发送一个对象,该对象包含您希望在视图模型之间来回发送的任何数据。

我强烈建议在使用 mvvm 时使用框架,这样会更容易。MVVM 框架比较是通过一些主要框架比较的答案的链接。

于 2012-04-09T13:58:02.740 回答