【问题标题】:Custom Commands in wpfwpf中的自定义命令
【发布时间】:2011-07-18 18:28:34
【问题描述】:

我正在开发一个 WPF 应用程序,它有一个工具栏/菜单,可用于多个自定义命令。大概15-20左右吧。我已经看过有关如何创建自定义命令的文档,但它们都不一定适用于我正在尝试做的事情。

我正在使用控制器来处理我的应用程序中的业务逻辑,并且我试图让我的视图根本不做任何逻辑。

我想做的是在我的项目中创建一个包含自定义命令类的目录,以便我可以将它们与控制器和视图分离,但我仍然希望从视图中调用它们,例如正常的命令是。

我也看到了 DelegateCommand 类的使用,但不太确定这是否是我想要的方向。

我希望能够有一个任意的自定义命令类,如下所示

public CustomCommand: ICommandd
{
    public bool CanExecute(object parameter)
    {
        //arbitrary logic
    }

    public void Execute(object parameter)
    {

    }
}

我的想法是我将拥有 10 到 20 个,并且我希望将它们与其他所有内容分开,并在需要时调用它们。

我知道有一种方法可以分隔我的自定义命令,但不太确定。

我是使用命令的新手,所以我仍在努力掌握这个概念。

谢谢,

【问题讨论】:

    标签: c# wpf command


    【解决方案1】:

    这个概念是你将一个命令绑定到一个按钮,命令驱动这个按钮的两个属性:“点击时”和“启用”,从而产生你发布的界面。

    您想要执行命令的主要原因是能够将按钮单击绑定到视图模型中的操作。

    如果您创建一个将操作作为构造函数参数的自定义命令,您可以将视图模型中的方法直接连接到您的命令。

    public class RelayCommand: ICommandd
    {
        Action action;
        Func<bool> canExecute;
    
        public RelayCommand(Action action) : this(action, () => true) {}
        public RelayCommand(Action action, Func<bool> canExecute) 
        { 
            this.action = action; 
            this.canExecute = canExecute;
        }
    
        public bool CanExecute(object parameter)
        {
            return canExecute();
        }
    
        public void Execute(object parameter)
        {
            action();
        }
    }
    

    在您的视图模型中的用法是

    public RelayCommand SaveCommand { get; set; }
    
    SaveCommand = new RelayCommand(OnSave);
    
    public void Save()
    {
        // save logic...
    }
    

    如果你想连接 CanExecute,你也可以使用第二个 ctor 并提供一个 CanSave 方法。

    public RelayCommand SaveCommand { get; set; }
    
    SaveCommand = new RelayCommand(OnSave, CanSave);
    
    public void Save()
    {
        // save logic...
    }
    
    public bool CanSave()
    {
        return // ... 
    }
    

    您可能注意到我在实现中删除了命令参数。这在大多数情况下就足够了,并且可以在处理程序方法中为您节省额外的参数。对于剩下的 10%,我实现了一个 RelayCommand&lt;T&gt;,它采用 Action 而不是 Action,并将 Execute 方法更改为

        public void Execute(object parameter)
        {
            action((T)parameter);
        }
    

    需要参数化处理程序

    SaveCommand = new RelayCommand<SomeType>(OnSave);
    
    public void Save(SomeType toSave)
    {
        // save logic using parameter
    }
    

    这可以避免您在使用 object 变量时遇到的所有转换问题,并确保您的视图模型类型安全。

    【讨论】:

    • 这确实是一种非常有用的命令方式,尤其是对于 MV-VM 架构,但不幸的是,这并不是我想要的,如果你在上面阅读,我实际上是在寻找分离所有我认为的逻辑,我有这样做的具体原因,我实际上在这里找到了我想要的东西codeproject.com/KB/WPF/… - 为你的好例子投票,谢谢!
    • 即使您想通过静态类提供命令,我也建议您使用 RelayCommands。这样,您的 xaml 文件就不需要任何代码,_DeleteContact = new RoutedUICommand("Delete an existing contact", "DeleteContact", typeof(MyAppCommands)); 包含硬编码的字符串,这些字符串可能会改变并阻碍重构。我会对你的用例感兴趣。为什么要将所有命令放在一个静态类中?
    【解决方案2】:

    使用RelayCommand,它不需要您为每个命令创建一个类,您只需将这两个方法作为 lambda 表达式/委托添加到构造函数中。

    我在所有项目中都使用它,它可以真正节省时间。

    【讨论】:

      【解决方案3】:

      我最终通过以下帖子回答了我自己的问题, http://www.codeproject.com/KB/WPF/CentralizingWPFCommands.aspx?display=Print

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-12-26
        • 2010-09-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-10-10
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多