Выполнение одной и той же команды Prism из разных ViewModels

Можно ли как-то выполнить одну команду из другой ViewModels в приложении WPF с помощью Prism?

Позвольте мне объяснить, что я имею в виду.

У меня есть класс MainMenuViewModel:

public class MainMenuViewModel
{
    private ICommand _aboutCommand;
    public ICommand AboutCommand
    {
        get
        {
            if (_aboutCommand == null)
            {
                _aboutCommand = new DelegateCommand(() => 
                    { MessageBox.Show("About menu item clicked!"); });
            }

            return _aboutCommand;
        }
    }
}

также есть View для этой модели:

<Menu IsMainMenu="True">
    <MenuItem Header="Nápověda">
        <MenuItem Header="O Aplikaci" x:Name="About" 
                  Command="{Binding AboutCommand}" />
    </MenuItem>
</Menu>

В приложении есть еще один модуль, который должен выполнить команду с таким же поведением (или даже, наверное, лучше - ту же команду):

public class MunisatorViewModel
{
    private ICommand _aboutCommandInAnotherModule;

    public ICommand AboutCommandInAnotherModule
    {
        get
        {
            if (_aboutCommandInAnotherModule== null)
            {
                _aboutCommandInAnotherModule= new DelegateCommand(() =>
                    { MessageBox.Show("About menu item clicked!"); });
            }

            return _aboutCommandInAnotherModule;
        }
    }
}

этот модуль имеет представление:

<StackPanel Background="White" HorizontalAlignment="Center" VerticalAlignment="Top">
    <Button cmd:Click.Command="{Binding AboutCommandInAnotherModule}">About</Button>
</StackPanel>

Можно ли избежать дублирования кода?

P.S. Я понимаю, что я могу создать базовый класс для этих двух ViewModels и описать там эти команды, но проблема в том, что некоторые ViewModels уже имеют разные базовые классы.


person msi    schedule 07.03.2012    source источник


Ответы (2)


Используйте EventAggregator для создания подобных событий. Это позволяет вам иметь слабосвязанную связь между различными областями пользовательского интерфейса.

Концепция публикации/подписки, передача данных через реализацию объекта CompositeEvent работает хорошо.

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

документация Prism подробно описывает ваши варианты .

Надеюсь, это поможет.

person Simon Whittemore    schedule 07.03.2012
comment
Я знаю о EventAggregator, но в данной ситуации это не помогает избежать дублирования кода. - person msi; 08.03.2012
comment
Да, это так... MainMenuViewModel реализует код для отображения меню «О программе». Он также подпишется на событие под названием AboutCommandFired, и MunisatorViewModel опубликует это событие. В вашей модели MainMenuViewModel вам также может понадобиться переместить реализацию из анонимного метода, чтобы его можно было вызывать как из DelegateCommand, так и из агрегатора событий. - person lecrank; 08.03.2012
comment
Но в этом случае все же я должен дублировать код для создания команды и назначать разные команды для представлений. И мой вопрос заключался в том, можно ли использовать реализацию SAME Command для разных представлений. - person msi; 08.03.2012

Возможно, вы могли бы преобразовать свой AboutCommand в отдельный класс/объект, который затем можно было бы внедрить в обе модели представления (конструктор, сеттер...). Таким образом, каждая модель представления будет просто доставлять ссылку на объект команды, и будет дублированный код по цене «аутсорсинга» вашей логики AboutCommand из вашей основной модели представления.

Другим более статическим способом может быть использование командного прокси, который содержит CompositeCommands, например, ваш AboutCommand. Везде, где вы могли бы затем зарегистрировать (или несколько) реализации для команды about.

Надеюсь это поможет.

person Andreas H.    schedule 11.03.2012