如何在WPF中绑定命令

有时我们使用复杂的方法很多次,我们忘记了完成任务的最简单方法。

我知道如何进行命令绑定,但我总是使用相同的方法。

创建一个实现ICommand接口的类,并从视图模型中创建该类的新实例,绑定就像一个魅力。

这是我用于命令绑定的代码

public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); DataContext = this; testCommand = new MeCommand(processor); } ICommand testCommand; public ICommand test { get { return testCommand; } } public void processor() { MessageBox.Show("hello world"); } } public class MeCommand : ICommand { public delegate void ExecuteMethod(); private ExecuteMethod meth; public MeCommand(ExecuteMethod exec) { meth = exec; } public bool CanExecute(object parameter) { return false; } public event EventHandler CanExecuteChanged; public void Execute(object parameter) { meth(); } } 

但我想知道这样做的基本方法,没有第三方dll没有新的类创建。 使用单个类执行此简单命令绑定。 实际的类从ICommand接口实现并完成工作。

Prism已经提供了Microsoft.Practices.Prism.Commands.DelegateCommand

我不确定它是否被视为第三方。 至少它是官方的,并在MSDN上记录。

一些本机内置命令如copy,paste实现ICommand接口。 恕我直言,它遵循开放(扩展)/关闭(改变)原则。 这样我们就可以实现自己的命令。


更新

正如WPF Commanding 在此记录 ,摘录……

WPF提供了一组预定义命令。 如Cut,BrowseBack和BrowseForward,Play,Stop和Pause。

如果命令库类中的命令不满足您的需要,则可以创建自己的命令。 有两种方法可以创建自定义命令。 第一个是从头开始实现ICommand接口。 另一种方式, 更常见的方法是创建RoutedCommand或RoutedUICommand 。

我在开始时尝试过RoutedCommand模型,最后实现了ICommand。

示例XAML绑定

  

RoutedCommand与RoutedEvent没有什么不同。 这似乎是一个更好的按钮的’Clicked’事件处理程序。 它的目的是:将应用程序逻辑与View分开但需要一些附加DependencyProperty或代码隐藏。

我个人觉得只需要实现我的ICommand就更舒服了。

我倾向于使用内置RelayCommand的MVVM灯架。

您将ICommand属性添加到视图模型,然后为其分配一个relay命令: –

 ICommand ClickMeCommand {get;set;} private void InitCommands() { ClickMeCommand = new RelayCommand(()=>HasBeenClicked=true); //or ClickMeCommand = new RelayCommand(ClickMeEvent); } public void ClickMeEvent() { HasBeenClicked=true; } 

在xaml中你只需使用普通绑定: –

  

如果您不想创建新类,请使用routed命令。 这是一个小片段。 我已经创建了一个路由命令作为Save并将其绑定到命令绑定窗口,从button提起命令。瞧!我希望这可以帮助你

  public partial class Window1 : Window { public static readonly RoutedCommand Foo = new RoutedCommand(); public Window1() { InitializeComponent(); } void Foo_CanExecute(object sender, CanExecuteRoutedEventArgs e) { // The Window gets to determine if the Foo // command can execute at this time. e.CanExecute = true; } void Foo_Executed(object sender, ExecutedRoutedEventArgs e) { // The Window executes the command logic when the user wants to Foo. MessageBox.Show("The Window is Fooing..."); } }   

我希望我能理解你的问题。

PS:命令设计模式的需要是分离执行逻辑和命令调用程序.So Command类是一种封装逻辑的方法。

如果不在VS中运行代码来判断,你的问题是你调用InitializeComponent (渲染XAML),然后设置DataContext而不在test属性中有任何值,最后设置一个私有成员。 UI如何注意到您的Command不再为null(这是它在Property中找到的最后一个值)?

为什么不像这样懒洋洋地实现命令:

 public ICommand test { get { if(testCommand== null) { testCommand= new MeCommand(processor); } return testCommand; } } 

这样它就会在需要时立即存在,并且您不需要更改通知(除非您稍后在运行时更改该命令)。

顺便说一下,在命令绑定场景中,您可以感觉到没有代码正在执行的几个位置:

1)CanExecute()返回false:只返回true或根据您的业务案例进行评估。

2)CanExecute的条件发生变化,因此它将返回true,但不会被调用:您可以使用CommandManager类挂起Command,请参见此处 。 在尝试之前确保1)已解决。 这可以确保您的UI会经常重新查询CanExecute ,如果仍然不够,请显式调用Method CommandManager.InvalidateRequerySuggested()

3)你的绑定是错误的。 像这样更改绑定代码:

 Command="{Binding Path=test, PresentationTraceSources.TraceLevel=High}" 

只要拉动或推动绑定的值,这将垃圾邮件输出窗口。 注意“使用最终值”这个术语。 如果它为null,则命令不是它应该的位置(还)。

好吧,你几乎拥有它。 只需确保CanExecute()将返回true,否则您的代码将不会被执行。 (我认为它实际上会,但仍然)。 还要确保将“NotifyPropertyChanged(’yourCommand’)”添加到

  public ICommand test { get { return testCommand; } set { testCOmmand = value; NotifyPropertyChanged("test"); } } 

到这里。

你也可以做test = new MeCOmmand(); DataContext = this;

在WPF窗口构造函数中,要链接键盘快捷键,只需使用委托添加绑定,并将其与键手势相关联。

 public YourWindow() //your constructor { ... //bind keyboard command shortcuts InputBindings.Add(new KeyBinding( //add a new key-binding, bind it to your command object which takes a delegate new WindowCommand(this) { ExecuteDelegate = TogglePause //REPLACE TogglePause with your method delegate }, new KeyGesture(Key.P, ModifierKeys.Control))); ... } 

创建一个简单的WindowCommand类,它接受一个执行委托来触发它上面的任何方法集。

 public class WindowCommand : ICommand { private MainWindow _window; public Action ExecuteDelegate { get; set; } public WindowCommand(MainWindow window) { _window = window; } public bool CanExecute(object parameter) { return true; } public event EventHandler CanExecuteChanged; public void Execute(object parameter) { if (ExecuteDelegate != null) { ExecuteDelegate(); } else { throw new InvalidOperationException(); } } }