MVVM - Заполнение поля со списком и как передать команды из окна в пользовательский контроль - PullRequest
0 голосов
/ 04 апреля 2011

У меня есть ItemType от EF. Этот ItemType обернут в ItemTypeViewModel. Многие ItemTypes заключены в ItemTypeViewModels и помещаются в ObservableCollection в ViewModel для пользовательского элемента управления, который их отображает:

Screen2

Я использую CollectionView, чтобы просматривать их. Экран выглядит так:

Screen

Теперь я думаю, что кнопки, используемые для подкачки, которые находятся в пользовательском элементе управления, могли бы быть лучше размещены в окне, которое будет содержать пользовательский элемент управления. Итак, в моем пользовательском контроле я знаю, что есть такие команды:

enter image description here

Но я хочу, чтобы они были в окне. Я не знаю, будет ли это хорошим дизайном, но если я справлюсь с этим, как передать команды из окна в usercontrol?

Другой вопрос, который у меня есть, - как заполнить поле со списком в пользовательском элементе управления. Они всегда будут иметь одинаковые значения, но выбранный элемент будет меняться в зависимости от типа элемента.

1 Ответ

0 голосов
/ 04 апреля 2011

Я знаю два способа, как это сделать.

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.

1-е решение лучше для меня, но в то же время я довольно часто использую класс Messenger.Это зависит от ситуации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...