Выполнить метод в другом элементе управления, используя MVVM - PullRequest
0 голосов
/ 11 октября 2018

Я создал пустышку UserControl, у которой в коде есть метод для отображения сообщения!Я использовал этот элемент управления в своем главном окне и хочу выполнить его метод, когда я нажимаю Button с помощью команд и MVVM.Как я могу это сделать?

<UserControl x:Class="ControlBining.Control1"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <Grid DataContext="{Binding RelativeSource={RelativeSource AncestorType=UserControl}}">
    </Grid>
</UserControl>

C #:

public partial class Control1 : UserControl
   {
      public Control1()
      {
         InitializeComponent();
      }

      public void ShowMessage()
      {
         MessageBox.Show("Called from other control!");
      }
   }

MainWindow XAML:

<Window x:Class="ControlBining.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:ControlBining"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.DataContext>
        <local:ViewModel/>
    </Window.DataContext>
    <StackPanel Margin="0 50 0 0">
        <local:Control1 Width="100"/>
        <Button Width="100" Content="Show Message"/>
    </StackPanel>
</Window>

RelayCommand:

   public class RelayCommand : ICommand
   {
      private readonly Predicate<object> m_canExecute;
      private readonly Action<object> m_execute;

      public RelayCommand(Predicate<object> canExecute, Action<object> execute)
      {
         m_canExecute = canExecute;
         m_execute = execute;
      }

      public event EventHandler CanExecuteChanged
      {
         add => CommandManager.RequerySuggested += value;
         remove => CommandManager.RequerySuggested -= value;
      }

      public bool CanExecute(object parameter)
      {
         return m_canExecute(parameter);
      }

      public void Execute(object parameter)
      {
         m_execute(parameter);
      }
   }

В настоящее времяЯ заставил это работать, но я действительно не уверен, что это хороший дизайн:

Код контроля

  private void Control1_Loaded(object sender, RoutedEventArgs e)
  {

     ViewModel m = (ViewModel)DataContext;
     m.ShowMessage += M_ShowMessage;
  }

  private void M_ShowMessage()
  {
     ShowMessage();
  }

ВViewModel

  public event Action ShowMessage;

  private ICommand m_showMessageCommand;
  public ICommand ShowMessageCommand
  {
     get
     {
        return m_showMessageCommand ?? (m_showMessageCommand = new RelayCommand(
                  p => true,
                  p => ShowMessage?.Invoke()));
     }
  }

XAML:

1 Ответ

0 голосов
/ 11 октября 2018

Если вам просто нужно показать сообщение, вы должны переместить метод ShowMessage() в модель представления и использовать службу сообщений для этого из класса модели представления.

Если вы действительно хотите вызватьнекоторый метод, который имеет смысл определять только в представлении, это можно сделать, реализовав интерфейс в представлении и внедрив модель представления с этим интерфейсом.Например, когда вы вызываете команду:

public interface IView
{
    void ShowMessage();
}

public partial class Control1 : UserControl, IView
{
    public Control1()
    {
        InitializeComponent();
    }

    public void ShowMessage()
    {
        MessageBox.Show("Called from other control!");
    }
}

Модель представления:

public ICommand ShowMessageCommand
{
    get
    {
        return m_showMessageCommand ?? (m_showMessageCommand = new RelayCommand(
                  p => true,
                  p =>
                  {
                      IView view as IView;
                      if (view != null)
                      {
                          //...
                          view.ShowMessage();
                      }
                  }));
    }
}

Модель представления ничего не знает о представлении, она знает только об интерфейсечто, конечно, можно назвать чем-то иным, чем IView.

Другой вариант заключается в использовании агрегатора событий или мессенджера для отправки события или сообщения из модели представления в представление в сильно связанном виде.,Пожалуйста, обратитесь к этому сообщению в блоге для получения дополнительной информации об этом.

Ни один из подходов не нарушает шаблон MVVM.

...