Любой WinRT iCommand/CommandBinding реализует образцы там?
Абстрактные команды в Модели просмотра являются ценной практикой с проектами XAML/MVVM. Я понимаю. И я вижу, что ICommand находится в WinRT; но как мы его реализуем? Я не нашел образец, который действительно работает. Кто-нибудь знает?
Ответы
Ответ 1
Мое любимое время всегда должно быть DelegateCommand, предоставленное командой PnP. Он позволяет создать типизированную команду:
MyCommand = new DelegateCommand<MyEntity>(OnExecute);
...
private void OnExecute(MyEntity entity)
{...}
Он также позволяет создать способ для события CanExecuteChanged (для отключения/включения команды)
MyCommand.RaiseCanExecuteChanged();
Здесь код:
public class DelegateCommand<T> : ICommand
{
private readonly Func<T, bool> _canExecuteMethod;
private readonly Action<T> _executeMethod;
#region Constructors
public DelegateCommand(Action<T> executeMethod)
: this(executeMethod, null)
{
}
public DelegateCommand(Action<T> executeMethod, Func<T, bool> canExecuteMethod)
{
_executeMethod = executeMethod;
_canExecuteMethod = canExecuteMethod;
}
#endregion Constructors
#region ICommand Members
public event EventHandler CanExecuteChanged;
bool ICommand.CanExecute(object parameter)
{
try
{
return CanExecute((T)parameter);
}
catch { return false; }
}
void ICommand.Execute(object parameter)
{
Execute((T)parameter);
}
#endregion ICommand Members
#region Public Methods
public bool CanExecute(T parameter)
{
return ((_canExecuteMethod == null) || _canExecuteMethod(parameter));
}
public void Execute(T parameter)
{
if (_executeMethod != null)
{
_executeMethod(parameter);
}
}
public void RaiseCanExecuteChanged()
{
OnCanExecuteChanged(EventArgs.Empty);
}
#endregion Public Methods
#region Protected Methods
protected virtual void OnCanExecuteChanged(EventArgs e)
{
var handler = CanExecuteChanged;
if (handler != null)
{
handler(this, e);
}
}
#endregion Protected Methods
}
Ответ 2
Отъезд RelayCommand class (только код METRO). Класс NotifyPropertyChanged
можно найти здесь. Класс NotifyPropertyChanged
используется только для привязки на CanExecute
и обновляет его с помощью RaiseCanExecuteChanged
.
Исходный класс команд реле можно найти здесь
Ответ 3
К сожалению, похоже, что нет родного класса, который реализует его для вас. Интерфейс не слишком сложный, если вы хотите его реализовать самостоятельно, а популярный инструментарий MVVM Lite включает в себя собственную версию RelayCommand. Вы можете добавить MVVM Lite в свой проект, щелкнув правой кнопкой мыши ссылку и выбрав "Управление пакетами NuGet". Если у вас нет этой опции, включите Nuget под Инструменты → Расширения и обновления.
Ответ 4
Я искал минимальную сквозную реализацию команды XAML-MVVM и еще не нашел ее.
Итак, после ответа #Rico у меня получилось следующее как минимальная RelayCommand, которая работает. Я использую аналогичную минимальную версию в большом проекте.
public class RelayCommand : System.Windows.Input.ICommand {
readonly Action<object> execute;
public RelayCommand(Action<object> execute) {
this.execute = execute;
}
public bool CanExecute(object parameter) {
return true;
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter) {
this.execute(parameter);
}
}
Чем больше класс RelayCommand предоставляет больше контроля над CanExecute
и CanExecuteChanged
, но для этого вам не нужно, и вам может вообще не понадобиться.
Чтобы использовать его в модели просмотра:
class ViewModel : INotifyPropertyChanged {
<< ... snip VM properties and notifications ...>>
public RelayCommand DoSomethingCommand {
get {
return new RelayCommand(param => {
this.DoSomething(param as AType);
Debug.WriteLine("Command Executed");
});
}
}
}
(Нам не нужен INotifyPropertyChanged для Command, но любая модель представления обычно реализует его.)
Наконец, XAML...
<Grid>
<!-- Set the data context here, for illustration. -->
<Grid.DataContext>
<local:ViewModel/>
</Grid.DataContext>
<!-- A sample control bind to a property -->
<TextBlock
Text="{Binding AProp}"/>
<!-- Bind a command -->
<Button Command="{Binding DoSomethingCommand}" CommandParameter="foo">Change!</Button>
</Grid>
Ответ 5
Я нашел этот действительно хороший пример в
https://code.msdn.microsoft.com/windowsapps/Working-with-ICommand-690ba1d4
<Page.Resources>
<local:MyCommandsCollection x:Key="MyCommands" />
</Page.Resources>
<Button Width="280"
Height="59"
Margin="513,280,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Command="{Binding MyFirstCommand}"
CommandParameter="{Binding Text,
ElementName=myTextBox}"
Content="Execute Command" />
public class MyCommandsCollection
{
public MyCommand MyFirstCommand
{
get { return new MyCommand(); }
}
}
public class MyCommand : ICommand
{
public bool CanExecute(object parameter)
{
return true;
}
public event EventHandler CanExecuteChanged;
public async void Execute(object parameter)
{
MessageDialog message = new MessageDialog(
"The command is executing, the value of the TextBox is " + parameter as String);
await message.ShowAsync();
}
}
Я пробовал это с помощью x: Bind, и он работает хорошо. Все, что мне нужно, - это открыть свойство в моей модели ViewModel, которая возвращает новый экземпляр класса "MyCommand", и все это хорошо.
Поскольку я устанавливаю DataContext в свой XAML, мне не нужно было связываться с каким-либо материалом "MyCommandCollection". Yay скомпилировал привязку.