2016-09-30 75 views
1

我想实现一个自定义WPF命令我搜查,发现下面的代码:
实现自定义WPF命令

public static class CustomCommands 
{ 
    public static readonly RoutedUICommand Exit = new RoutedUICommand 
    (
     "Exit", 
     "Exit", 
     typeof(CustomCommands), 
     new InputGestureCollection() 
     { 
      new KeyGesture(Key.F4, ModifierKeys.Alt) 
     } 
    ); 

    //Define more commands here, just like the one above 
} 


有一些我无法找出两件事情。

  1. 是否有必要拥有命令static readonly?不能,我们只是使用const来声明它?

  2. 究竟是什么new InputGestureCollection() { new KeyGesture(Key.F4, ModifierKeys.Alt) }是?如果它正在调用默认构造函数并初始化属性,那么应该有一个要分配的属性,但没有任何要分配的属性。 InputGestureCollection有大括号,但大括号内没有初始化任何属性。怎么样?这种说法是什么?

回答

6

Nooo, 这不是一个好的方法。

首先,你需要对MVVM和WPVM有一些基本的了解。 你有一个你将要绑定到你的UI的类。该类不是.xaml.cs

它完全独立于视图。你需要通过调用某事像那把类的实例到你可以在.xaml.cs做这个窗口的DataContext:

this.DataContext = new MyViewModel(); 

现在你的类MyViewModel需要类型的ICommand的属性。最佳做法是制作一个实现ICommand的类。通常你称它为DelegateCommand或RelayCommand。 例子:

public class DelegateCommand : ICommand 
{ 
    private readonly Predicate<object> _canExecute; 
    private readonly Action<object> _execute; 

    public event EventHandler CanExecuteChanged; 

    public DelegateCommand(Action<object> execute) 
     : this(execute, null) 
    { 
    } 

    public DelegateCommand(Action<object> execute, 
        Predicate<object> canExecute) 
    { 
     _execute = execute; 
     _canExecute = canExecute; 
    } 

    public bool CanExecute(object parameter) 
    { 
     if (_canExecute == null) 
     { 
      return true; 
     } 

     return _canExecute(parameter); 
    } 

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

    public void RaiseCanExecuteChanged() 
    { 
     if (CanExecuteChanged != null) 
     { 
      CanExecuteChanged(this, EventArgs.Empty); 
     } 
    } 
} 

然后在您的视图模型创建一个属性在它这个类的一个实例。像这样:

public class MyViewModel{ 

    public DelegateCommand AddFolderCommand { get; set; } 
    public MyViewModel(ExplorerViewModel explorer) 
    {   
     AddFolderCommand = new DelegateCommand(ExecuteAddFolderCommand, (x) => true); 
    } 

    public void ExecuteAddFolderCommand(object param) 
    {   
     MessageBox.Show("this will be executed on button click later"); 
    } 
} 

在您的视图中,您现在可以将按钮的命令绑定到该属性。

<Button Content="MyTestButton" Command="{Binding AddFolderCommand}" /> 

路由命令是默认情况下已存在的东西(复制,粘贴等)。如果你是MVVM的初学者,那么在对“正常”命令有基本的了解之前,你不应该考虑创建路由命令。

要回答你的第一个问题:使命令静态和/或const绝对不是必需的。 (请参阅MyViewModel类)

第二个问题:您可以使用默认值初始化列表,并将其放入{-方括号中。 例子:

var Foo = new List<string>(){ "Asdf", "Asdf2"}; 

您不必在初始化的特性对象。您有一个初始化的列表,然后使用{-方括号中的参数调用Add()

这就是你的情况基本上发生的情况。你有一个你用一些值初始化的集合。

+0

难道你不知道第一个问题吗?这很重要吗? – Media

+0

@media请参阅更新的答案 – Dominik

+0

我添加了关于第二个的额外信息 – Media

1

要回答你的第二个问题:

new InputGestureCollection() 
{ 
    new KeyGesture(Key.F4, ModifierKeys.Alt) 
} 

这是一个collection initializer的一个例子,等同于:

var collection = new InputGestureCollection(); 
collection.Add(new KeyGesture(Key.F4, ModifierKeys.Alt)); 

这只是一个速记,和一些ReSharper的建议。