2016-09-30 78 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的建議。