如何在WPF中绑定命令

时间:2012-12-12 11:36:11

标签: c# wpf icommand commandbinding

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

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

创建一个实现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接口实现并完成工作。

6 个答案:

答案 0 :(得分:15)

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

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

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


更新

WPF命令记录here,摘录......

  

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

     

如果命令库类中的命令不符合您的需求,   然后你可以创建自己的命令。有两种方法可以创建   自定义命令。首先是从头开始实施   ICommand接口。另一种方式,更常见的方法,   是创建RoutedCommandRoutedUICommand

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

示例XAML绑定

<CommandBinding Command="{x:Static custom:Window1.CustomRoutedCommand}"
                    Executed="ExecutedCustomCommand"
                    CanExecute="CanExecuteCustomCommand" />

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

就我个人而言,只要实现我的ICommand,我感觉更舒服。

答案 1 :(得分:3)

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

您将ICommand属性添加到视图模型,然后为其分配relaycommand: -

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

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

<Button Content='Push me' Command='{Binding ClickMeCommand}' />

答案 2 :(得分:2)

如果您不想创建新课程,请使用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...");
    }
}

 <Window.CommandBindings>
 <CommandBinding
  Command="{x:Static  local:Window1.Foo}"
  CanExecute="Foo_CanExecute"
  Executed="Foo_Executed"
  />

 

我希望我能很好地理解你的问题。

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

答案 3 :(得分:1)

如果不在VS中运行代码,判断你做了什么,问题是你调用InitializeComponent(渲染XAML),然后设置DataContexttest没有任何值属性,最后设置一个私有成员。 UI如何注意到你的命令不再为null(这是它在属性中找到的最后一个值)?

为什么不像这样懒惰地发布命令:

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

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

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

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

2)CanExecute的条件发生变化,因此它将返回true,但不会被调用:您可以使用CommandManager类挂起Command,请参阅here。在尝试之前,请确保1)已解决。这可以确保您的用户界面会频繁地重新查询CanExecute,如果仍然不够,请明确调用方法CommandManager.InvalidateRequerySuggested()

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

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

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

答案 4 :(得分:0)

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

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

到这里。

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

答案 5 :(得分:0)

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