14

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

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

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

4

6 回答 6

16

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

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

一些本机内置命令,如复制、粘贴,实现了 ICommand 接口。恕我直言,它遵循打开(用于扩展)/关闭(用于更改)原则。这样我们就可以实现自己的命令。


更新

正如 WPF 命令在此处记录的那样,摘录...

WPF 提供了一组预定义的命令。例如 Cut、BrowseBack 和 BrowseForward、播放、停止和暂停。

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

我一开始就尝试了 RoutedCommand 模型,最终实现了 ICommand。

示例 XAML 绑定

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

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

我个人觉得只实现我的 ICommand 会更舒服。

于 2012-12-12T12:07:29.720 回答
3

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

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

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}' />
于 2012-12-20T16:38:44.297 回答
2

如果您不想创建新类,请使用路由命令。这是一个小片段。我创建了一个路由命令作为 Save 并将其绑定到 window 的命令绑定,从 button.and 发出命令,瞧!.....我希望这可以帮助你

 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:命令设计模式的需要是将执行的逻辑和命令的调用者解耦,所以Command类是一种封装逻辑的方式。

于 2012-12-20T05:38:39.160 回答
1

从您在 VS 中不运行代码的情况下所做的判断,您的问题是您调用InitializeComponent(渲染 XAML),然后设置属性中DataContext没有任何值test,最后设置一个私有成员。UI 应该如何注意到您的 Command 不再为空(这是它在属性中找到的最后一个值)?

为什么不像这样懒惰地实例化命令:

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

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

顺便说一句,有几个地方你会感觉在命令绑定场景中没有执行任何代码:

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

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

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

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

每当绑定的值被拉出或推送时,这都会向您的输出窗口发送垃圾邮件。请注意“使用最终值”一词。如果它为空,则您的 Command 不在它应该在的位置(还)。

于 2012-12-18T12:11:06.610 回答
0

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

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

到这里。

你也可以做 test = new MeCOMmand(); 数据上下文 = 这个;

于 2012-12-16T09:38:28.543 回答
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();
        }
    }
}
于 2016-07-27T00:02:20.747 回答