2014-12-16 3 views
1

В настоящее время я изучаю, как реализовать команды в проектах C#/WPF. Предположим, что у меня есть класс MyClass с простой командой MyCommand.Метод вызова после выполнения дочерней команды

public class MyClass 
{ 
    private RelayCommand _myCommand; 
    public ICommand MyCommand 
    { 
     get 
     { 
      if (_myCommand == null) 
       _myCommand = new RelayCommand(_ => ExecuteMyCommand()); 
      return _myCommand; 
     } 
    } 

    private void ExecuteMyCommand() 
    { 
     // Do work... 
    } 
} 

Теперь предположим, что я создал ObservableCollection<MyClass> в модели представления, который связан с ListView. ListView имеет GridViewColumn с кнопками, привязанными к MyCommand. Все отлично работает.

public class MyViewModel 
{ 
    private ObservableCollection<MyClass> _myCollection; 
    public ObservableCollection<MyClass> MyCollection 
    { 
     get { return _myCollection; } 
     set 
     { 
      _myCollection = value; 
      RaisePropertyChanged("MyCollection"); 
     } 
    } 

    public void Refresh() 
    { 
     // Do work to refresh MyCollection to it's "live" state 
    } 
} 

Теперь мне нужно вызвать метод Refresh() на модели представления после того, как один из объектов в MyCollection выполняющей МояКоманда, но я не знаю, как подойти к этой ситуации.

вещи я попытался:

  • Добавление ссылки на модели представления в процессе строительства MyClass, позволяя команду для вызова Refresh() на с помощью ссылки модели представления то, когда команда выполняет. Это работает отлично, но мне действительно не нравится код - он чувствует себя грязным, чтобы ссылаться на конкретную модель представления, особенно когда он используется в других частях программы.

Вещи, которые я рассмотрел:

  • Изменение Refresh() для метода расширения для ObservableCollection<MyClass>, добавив ссылочный свойство, как упоминалось ранее, но ссылки на ObservableCollection вместо модели представления, которые не чувствовали бы себя как беспорядочный, но все еще не очень совершенный в моих глазах ...

Что было бы лучшим/правильным способом подойти к этой проблеме?

+0

Я не вижу вопрос здесь ... – Ben

+0

@Ben The вопрос был более или менее подразумеваемым «как мне следует продолжить?», но я добавил еще одну строку только для вас. – learningcs

ответ

1

Другой способ превратить это на следующий:

<MenuItem Content="Run MyCommand" 
      Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}, Path=DataContext.RefreshCommand}" 
      CommandParameter="{Binding}"/> 

Тогда в вашем MyViewModel

public class MyViewModel 
{ 
    private ObservableCollection<MyClass> _myCollection; 
    public ObservableCollection<MyClass> MyCollection 
    { 
     get { return _myCollection; } 
     set 
     { 
      _myCollection = value; 
      RaisePropertyChanged("MyCollection"); 
     } 
    } 

    //... 

    private ICommand _refreshCommand; 
    public ICommand RefreshCommand 
    { 
     get 
     { 
      if (_refreshCommand== null) 
       _refreshCommand= new RelayCommand<MyClass>(p => Refresh(p)); 
      return _refreshCommand; 
     } 
    } 

    public void Refresh(MyClass parameter) 
    { 
     if (null == parameter) 
      return; 
     parameter.ExecuteMyCommand(); 
     // Do work to refresh MyCollection to it's "live" state 
    } 
} 

Примечание: В настоящее время вы не должны иметь MyCommand на каждом MyClass экземпляр - вы можете передать его в качестве параметра в родительскую модель представления.

Не могу сказать, что есть вправо для выполнения вашей задачи. Поэтому я не могу сказать, какой из них лучше.

+0

Мне нравится это решение даже больше, чем мое - я думаю, что команды на самом деле не принадлежат объектам коллекции, потому что класс не должен содержать код, который относится к взаимодействию с представлением, поэтому это очень приятно. Кроме того, каждый объект не будет содержать свой собственный экземпляр команды, что, безусловно, хорошо. Я попытаюсь получить эту работу сейчас ... – learningcs

+0

Работает отлично, спасибо огромное! Я переместил все команды с объектов коллекции и в модель представления, но оставил методы, выполняемые командами на объектах. Я очень доволен этим решением! – learningcs

0

Мне удалось заставить это работать (я думаю) очень красиво.

Прежде всего, я изменил команду Refresh() на команду. Затем я добавил параметр в метод MyCommand. Метод выполняет свою работу, а затем проверяет параметр, чтобы увидеть, является ли это командой, а затем выполняет его.

private void ExecuteMyCommand(object param) 
{ 
    // Do work... 
    if (param != null && param is ICommand) 
     ((ICommand)param).Execute(null); 
} 

Тогда в XAML для вида, я поставил CommandParameter в команду, я хочу его запустить после этого.

<MenuItem Content="Run MyCommand" 
      Command="{Binding UploadCommand}" 
      CommandParameter="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}, Path=DataContext.RefreshCommand}"/> 

Если в XAML не задан параметр CommandParameter, он пропускает значение null. Совершено ...

0

Вы также можете поместить событие щелчка на кнопках (они пузыриться к виду), и вызовите команду из кода за

+0

Хотя я был прав, я надеялся отойти от использования событий везде, где команды могли их заменить – learningcs

Смежные вопросы