MVVM - 填充组合框以及如何将命令从窗口转发到用户控件

时间:2011-04-04 13:05:20

标签: wpf mvvm

我有一个来自EF的ItemType。此ItemType包装在ItemTypeViewModel中。许多ItemTypes包装在ItemTypeViewModels中,并被放入ViewModel中的ObservableCollection中,用于显示它们的用户控件:

Screen2

我使用CollectionView,因此我可以浏览它们。屏幕看起来像这样:

Screen

现在我认为用户控件中用于分页的按钮最好放在包含用户控件的Window中。所以,在我的用户控件中,我知道有这样的命令:

enter image description here

但我希望他们在窗口。我不知道这是不是很好的设计,但是如果我将通过这个,如何将命令从窗口中继到用户控件?

我的另一个问题是如何在用户控件中填充组合框。它们将始终具有相同的值,但所选项目将根据ItemType更改。

1 个答案:

答案 0 :(得分:0)

我知道如何做到这两点。

1)添加新课程,例如MainWindowViewModel并添加2个命令和UserControlViewModel的实例(您还没有说出标题,所以我会以这种方式称呼它)。以下是一部分示例:

public class MainWindowViewModel
{
    public UserControlViewModel ChildControlViewModel { get; set; }

    private Lazy<RelayCommand> nextCommand = new Lazy<RelayCommand>(() => 
        new RelayCommand(
            () => this.ChildControlViewModel.CollectionView.MoveCurrentToNext(),
            () => this.ChildControlViewModel.CollectionView.CurrentPosition < this.ChildControlViewModel.ItemTypes.Count - 1)); 

    public ICommand NextCommand
    {
        get { return nextCommand.Value; }
    }

    //prev command...
}

我使用了Lazy类,但主要想法很明确:代码是相同的,除了调用this.ChildControlViewModel.CollectionView而不是CollectionView

2)使用Messenger类。

这种方式并不那么明显,它只有一个优点:视图模型连接松散。

public class MainWindowViewModel
{
    public const string NextCommandNotification = "NextCommand";
    public const string PreviousCommandNotification = "PreviousCommand";
    private bool isNextCommandEnabled;
    private bool isPreviousCommandEnabled;

    public MainWindowViewModel()
    {
        this.NextCommand = new RelayCommand(
                                () => Messenger.Default.Send(new NotificationMessage<MainWindowViewModel>(this, NextCommandNotification)), 
                                () => this.isNextCommandEnabled);
        //prev command...

        Messenger.Default.Register<NotificationMessage<UserControlViewModel>>(this,
                msg =>
                {
                    if (msg.Notification == UserControlViewModel.CurrentItemChangedNotification)
                    {
                        this.isNextCommandEnabled = msg.Content.CollectionView.CurrentPosition < msg.Content.ItemTypes.Count - 1;
                        this.NextCommand.RaiseCanExecuteChanged();
                        //prev command...
                    }
                });
    }

    public ICommand NextCommand { get; private set; }
    //prev command...
}

public class UserControlViewModel
{
    public const string CurrentItemChangedNotification = "CurrentItemChanged";

    public UserControlViewModel()
    {
        Messenger.Default.Register<NotificationMessage<MainWindowViewModel>>(this,
                msg =>
                {
                    if (msg.Notification == MainWindowViewModel.NextCommandNotification)
                        this.CollectionView.MoveCurrentToNext();
                    else if (msg.Notification == MainWindowViewModel.PreviousCommandNotification)
                        this.CollectionView.MoveCurrentToPrevious();
                });

        this.CollectionView.CurrentChanged += (s,e) => Messenger.Default.Send(new NotificationMessage<UserControlViewModel>(this, CurrentItemChangedNotification))
    }
}

我不确定此代码是否能正常运行。这并不容易解释。

当用户按下按钮时,MainWindowViewModel类会发送消息。 UserControlViewModel类处理消息,更改当前项的位置,并发送CurrentItemChangedNotification消息。 MainWindowViewModel类处理此消息并更新命令的CanExecute部分。

第一个解决方案对我来说更好,但同时我经常使用Messenger类。这取决于具体情况。