MVVM从其他ViewModel对ViewModel执行命令

时间:2012-04-08 07:18:07

标签: c# wpf mvvm icommand

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

  1. HDD
    • 内部
    • 外部
    • 闪存
  2. 此列表在数据库中定义如下:

        [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 SelectedCategory上创建了一个属性:HWDocumentViewModel。当双击发生时,我将此属性从SubCategoryViewModel设置为this。所以,在这个属性中是object,它执行了doubleclick事件委托。太好了,现在我在HWDocumentView模型中有一个用户选择的对象 所以,我需要将项目加载到ListView。但是,我会从 SubCategoryViewModel 中的方法加载它们吗?我不这么认为。相反,我应该通过为它们创建一个ViewModel并将它绑定到ListView来从Main View Model加载它们,对吗?但是,我如何从SubCategoryViewModel调用HWDocumentViewModel中的方法?我应该写一个静态方法 在HWDocumentViewModel上可以从SubCategoryViewModel访问?
    或者有没有办法,如何从SubCategoryViewModel调用在HWDocumentViewModel上定义的Command?

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

    非常感谢。

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

2 个答案:

答案 0 :(得分:5)

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

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

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

_mainViewModel.LoadCategoryCommand.Execute();

答案 1 :(得分:3)

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

上发布了答案

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

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