实现自定义WPF命令

时间:2016-09-30 09:48:06

标签: c# 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有大括号,但在大括号内,它没有初始化任何属性。怎么样?这种陈述是什么?

2 个答案:

答案 0 :(得分:6)

拿去, 这不是一个好方法。

首先,您需要通过MVVM对WPF有一些基本的了解。 您有一个要绑定到UI的类。该类不是.xaml.cs

它完全独立于View。您需要将类的实例放入Window的DataContext中,您可以在.xaml.cs中执行此操作,方法是调用sth:

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);
        }
    }
}

然后在ViewModel中创建一个属性,其中包含该类的实例。像那样:

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的初学者,在你基本理解&#34; normal&#34;之前,你不应该考虑创建路由命令。命令。

回答你的第一个问题:使Commands为static和/或const绝对没有必要。 (参见MyViewModel类)

您的第二个问题:您可以使用放入{括号中的默认值初始化列表。 示例:

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

您没有初始化属性的对象。您有一个初始化的列表,然后使用您放在Add()括号中的参数调用{

这也是你的情况基本发生的事情。您有一个使用某些值初始化的集合。

答案 1 :(得分:1)

回答你的第二个问题:

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

这是collection initializer的示例,相当于:

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

这只是一种速记,是ReSharper建议的东西。