В настоящее время я изучаю, как реализовать команды в проектах С#/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 "live" state
}
}
Теперь мне нужно вызвать метод Refresh() в модели представления после того, как один из объектов MyCollection выполнит MyCommand, но я не уверен, как подойти к этой ситуации.
Вещи, которые я пробовал:
Вещи, которые я рассмотрел:
ObservableCollection<MyClass>
, добавив свойство ссылки, как упоминалось ранее, но ссылаясь на ObservableCollection вместо модели представления, которое не будет чувствовать себя грязным, но все же не совсем идеальным в моих глазах...Каким будет лучший/правильный способ решения этой проблемы?
Другой способ включить это:
<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 "live" state
}
}
Примечание. В настоящее время вам не нужно иметь MyCommand
для каждого экземпляра MyClass
- вы можете передать его в качестве параметра в родительскую модель представления.
Я не могу сказать, что есть правильный способ выполнить вашу задачу. Поэтому я не могу сказать, какой из них лучше.
Вы также можете поместить событие click на кнопки (они пузырятся до представления) и вызвать команду из кода
Мне удалось заставить это работать (я думаю) довольно неплохо.
Прежде всего, я изменил 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. Готово...