MVVM 从其他视图模型在视图模型上执行命令

本文关键字:视图 模型 执行 命令 MVVM 其他 | 更新日期: 2023-09-27 18:30:20

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

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

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

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

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

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绑定到其中。因此,我可以在树视图中查看我的类别以及我定义和维护的层次结构。这工作得很好。在子类别视图模型中,通过 MouseDoubleClick 的附加行为定义了一个命令,该命令也绑定到 TreeView。因此,当用户双击 Item 时,在 SubViewCategoryModel 中定义的方法将执行特定的代码。子类别视图模型列表嵌套在HWDocumentViewModel中,这是我窗口的主要视图模型。我现在需要的是显而易见的:当用户双击 TreeView 中的项目时,我需要从数据库加载项目并在 ListView 中显示它们。我的观点是,在 HWDocumentViewModel 中,我需要定义一个项目集合,并根据 ListView 中的选定类别加载它们。但是,我不知道如何从SubCategoryViewModel在HWDocumentViewModel上执行方法。因为 :树视图绑定到子类别视图模型项的列表,因此当发生双击时,将执行子类别视图模型上的方法。我正在寻找一种方法,如何在主视图模型(HWDocumentViewModel)上执行方法。

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

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

多谢。

编辑:我的树视图的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>

MVVM 从其他视图模型在视图模型上执行命令

我不确定我是否看到了问题。您有一个子类别树,选择一个子类别时,相应的SubCategoryViewModel会在主HWDocumentViewModel上将自己设置为SelectedCategory。这似乎是一个合理的方法。

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

如果你真的必须使用命令来调用负载,那么只需在每个SubCategoryViewModel中保留对主HWDocumentViewModel的引用,并使用简单的命令调用该命令:

_mainViewModel.LoadCategoryCommand.Execute();

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

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

我强烈建议在使用 mvvm 时使用框架,它使事情变得容易得多。MVVM 框架比较是一个指向答案的链接,该答案通过一些主要框架的比较。