5

我正在尝试学习 MVVM 模式。我遇到的主要问题是学习我应该在哪里声明、创建和绑定命令对象。

2个例子:

  1. 我有一个主窗体,其作用类似于开关板或主菜单。选择按钮 1 和视图 1 显示,选择按钮 2 和视图 2 显示。伟大的。现在我想回到主窗体,所以我需要视图 1(和视图 2)上的一个按钮,称为“主菜单”。我应该在哪里定义命令和命令处理程序,以便我可以绑定到“ShowMainMenu”命令?我可以在 View2ViewModel 中创建它们,但是我无权显示主视图?或者,我可以在 MainView 模型中创建它,但是我如何在子视图模型中绑定到它们(我根据 mvvm 建议使用 RelayCommand 对象,它们不会冒泡到父视图。)

  2. 我在一个主窗口视图上显示了两个用户控件,我们称它们为 MainView、UC1 和 UC2。其中每一个都有 ViewModel MainViewModel、UC1ViewModel、UC2View Model。我在 UC1 上有一个名为“AddItem”的按钮。它应该在 UC2 的列表中添加一个项目。设置“AddItemCommand”并绑定到它的正确方法是什么。命令应该在 MainViewModel、Uc1ViewModel 还是 UC2ViewModel 中?我应该如何绑定它。

谢谢你的帮助。

4

2 回答 2

3

1) 您可以从一个基本 ViewModel 继承 View1Model 和 View2Model 并在那里定义 ShowMainMenu。

或(这是我的方法)

使用 ContentPresenter 创建 RootView,它将显示您的所有视图。使用属性 ViewContent 创建 RootVeiwModel。将 ContetnPresenter 的 Content 属性绑定到 RootViewModel 的 ViewContent 属性。您可以使用objectViewContent 类型,但我建议您定义 MainVView1Model、View1Model 和 View2Model 支持的接口。更改 ViewContent 必须引发 ProprtyChangedEvent。在 RootViewModel 中定义 ShowMainViewCommand,它只会将 ViewContent 更改为 MainViewModel(并将显示为 MainView)。然后将 View1 和 View2 中 Button 的 Command 属性绑定到该命令,例如:

{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type RootView}}, 
                         Path=DataContext.ShowMainViwe}

有一些代码可以解释我要说的内容:

根视图.xaml

...
<ContentPresenter Content={Binding ViewContent} />
...

RootViewModel.ca

class RootViewModel : INotifyPropertyCahnged
{
    ...
    private object _ViewContent;
    public object ViewContent
    {
        get {return _ViewContent;}
        set
        {
            _ViewContent = value;
            if (PropertyChanged != null)
            {
                PropertyChanged ("ViewContent");
            }

        }
    }

    private RelayCommand _ShowMainView;
    public ICommand ShowMainView
    {
        get 
        {
            if (_ShowMainView == null)
            {
                _ShowMainView = new RelayCommand(x => ViewContent = new MainViewModel());
            }
            return _ShowMainView;
        }
    }
    ...
}

2) 将对 MainViewModel 的引用添加到 UC1ViewModel 和 UC2ViewModel - 这是影响其他控件的方式。MainViwModel 必须包含包含 UC1ViewModel 和 UC2ViewModel 的属性 第二个用户控件的项必须包含在 ObservableCollection 中。

我只是通过代码向您展示它是如何工作的:

class UC1ViewModel : INotifyPropertyChanged
{
    ...
    private MainViewModel _Parent;
    public UC1ViewModel(MainViewModel parent)
    {
        _Panert = parent;
    }

    private RelayCommand _AddItemToUC2;
    public ICommand AddItemToUC2
    {
        get
        {
            if (_AddItemToUC2 = null)
            {
                // UC2Content is UC2ViewModel
                // Items is ObservableCollection
               _AddItemToUC2 = new RelayCommand(x => _Parent.UC2Content.Items.Add(...));
            }
            return AddItemToUC2;
        }
    }
    ...
}
于 2009-12-05T20:26:41.177 回答
2

MainModel 可以为每个 UCxViewModel 提供一个属性,或者更简单地说,是一个 ViewModel 列表。“Show”命令将创建相应的 UVxViewModel,订阅由 UVxViewModel 发布的“OnClose”事件,并将其添加到列表中。MainView 有一个绑定到此列表的控件(例如 Tab 控件)和定义要用于每个 UCxViewModel 的视图的 DataTemplates。当 UVxViewModel 触发其 OnClose 事件时,MainModel 将其从列表中删除,从而导致相应的视图“关闭”。

对于“添加项目”部分,视图模型应该共享相同的项目列表(模型)。然后 UC2ViewModel 可以添加一个项目,并且 UC1View 将得到更新(假设列表实现了 INotifyCollectionChanged)。

我发现这个解释对理解 MVVM 很有帮助。

于 2009-12-05T14:25:58.250 回答