【问题标题】:MVVM Execute Command on ViewModel from other ViewModel来自其他 ViewModel 的 ViewModel 上的 MVVM 执行命令
【发布时间】:2012-04-21 02:39:27
【问题描述】:

我现在正在为一个简单的任务苦苦挣扎大约 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 的视图模型,它绑定了我的 TreeView。因此,我可以在树视图中查看我的类别,并使用我定义和维护的层次结构。这工作得很好。在 SubCategoryViewModel 中,通过 MouseDoubleClick 的附加行为 定义了一个 Command,该行为也绑定到 TreeView。因此,当用户双击 Item 时,在 SubViewCategoryModel 中定义的方法将执行特定的代码。 SubCategoryViewModel 列表嵌套在 HWDocumentViewModel 中,这是我的窗口的主要 ViewModel。 我现在需要的很明显:当用户双击 TreeView 中的项目时,我需要从数据库中加载项目并在 ListView 中显示它们。我的意见是,在 HWDocumentViewModel 中,我需要定义一个 Items 的集合,并将它们相应地加载到 ListView 中的选定类别。但是,我不知道如何从 SubCategoryViewModel 对 HWDocumentViewModel 执行方法。因为:TreeView绑定到SubCategoryViewModel项列表,所以当DoubleClick发生时,SubCategoryViewModel上的方法被执行。我正在寻找一种方法,如何在主 ViewModel (HWDocumentViewModel) 上执行方法。

我试过这种方法:
我在HWDocumentViewModel 上创建了一个属性:public static SubCategoryViewModel SelectedCategory。发生双击时,我将 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>

【问题讨论】:

  • 你能添加你的treeview xaml吗?你的问题让我对这个问题感到困惑

标签: c# wpf mvvm icommand


【解决方案1】:

我不确定我是否发现了问题。你有一个子类别树,当一个被选中时,适当的SubCategoryViewModel 在主HWDocumentViewModel 上将自己设置为SelectedCategory。这似乎是一种合理的方法。

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

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

_mainViewModel.LoadCategoryCommand.Execute();

【讨论】:

  • 这是我想要的解决方案。但我有点困惑 - 我采用的方法,你说它是合理的 - 即在主视图模型上有一个静态属性并由其他视图模型设置。这是真正的 MVVM 方式吗?
  • 嗯,不是静态的。但一个正常的财产是好的IMO。您可以使用事件来解耦视图模型,但这对我来说似乎有点过头了。
【解决方案2】:

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

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

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

【讨论】:

  • +1。我已经看到消息传递(比如动画之类的东西)非常令人印象深刻,所以性能应该不错。
  • 那么,你说我需要实现一个完整的范例来获得一个基本的功能,比如从类别列表中选择类别项目?或者我需要利用整个框架来让它工作?
  • 消息传递和框架用于跨视图模型通信或视图到视图模型的通信,而不是简单的绑定。在 MVVM Light 中,您可以只使用您想要使用的部分并实现它们,但是使用已经为您创建的消息传递范式会产生很多意义,而不是创建自己的发布者/订阅者模型并实现它。如果您不想实现,则不需要实现整个框架,但是,通过实现一个框架可能会节省大量时间
  • 据我了解 - 框架是实现更复杂事物的一种方式。但在我看来,在我的场景中使用它就像用战车杀死一只蚂蚁;)。我会仔细看看 MVVM Light 框架,它看起来很强大 - 感谢您的提示
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-20
  • 1970-01-01
  • 2012-06-17
相关资源
最近更新 更多