【发布时间】:2016-01-12 03:55:48
【问题描述】:
我仍在学习 wpf,但是我熟悉如何在 wpf c# 中设置 mvvm。然而,当涉及到 ICommand/RelayCommand 的东西时,它对我来说有点令人困惑。在过去的几个月里,我编译了一些 ICommand 类的实现,以创建我的工具。但是,我现在已经阅读了几篇文章并且已经查看了足够长的代码,我正在寻找可以帮助我的人并简单地说这里发生了什么,如果是这样,我如何组合/清理这些类。目前代码似乎是多余的,我不确定如何优化它。希望这不是要求太多。谢谢。
我想在此维护的两件重要的事情是能够将参数传递给命令,如 RelayCommand 的第一个用法示例中所示。其次,启用/禁用命令的能力,如第二个命令所示。
所以在我的工具中我有这个助手类。 1.我没有得到这个RelayCommand.cs中两个类之间的使用差异。有一个公共类和一个内部类。 2. 两者都需要还是可以结合使用? RelayCommand.cs
using System;
using System.Windows.Input;
namespace WpfApplication1.Helper
{
public class RelayCommand<T> : ICommand
{
private readonly Action<T> execute;
private readonly Predicate<T> canExecute;
public RelayCommand(Action<T> execute, Predicate<T> canExecute = null)
{
if (execute == null)
throw new ArgumentNullException("execute");
this.execute = execute;
this.canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
if (parameter == null)
{
return true;
}
else
{
return canExecute == null || canExecute((T)parameter);
}
}
public void Execute(object parameter)
{
execute((T)parameter);
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
}
// added
internal class RelayCommand : ICommand
{
private readonly Predicate<object> canExecute;
private readonly Action<object> execute;
public RelayCommand(Action<object> execute, Predicate<object> canExecute = null)
{
if (execute == null)
throw new ArgumentNullException("execute");
this.execute = execute;
this.canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
return canExecute == null || canExecute(parameter);
}
public void Execute(object parameter)
{
execute(parameter);
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
}
}
我在名为 Customer.cs 的类对象中使用 RelayCommand.cs 的示例
private ICommand addNewLicense_Command;
public ICommand AddNewLicense_Command
{
get
{
return addNewLicense_Command ?? (addNewLicense_Command = new RelayCommand<Customer>(n =>
{
AddNewLicense_Execute(n);
}));
}
}
那么在我的 MainViewModel.cs 中,我在上面提到的 Helper 类所属的同一个项目中还有另一个 ICommand 类。这门课有必要吗?它看起来与 RelayCommand 类非常相似。
public class CommandHandler : ICommand
{
private Action _action;
private bool _canExecute;
public CommandHandler(Action action, bool canExecute)
{
_action = action;
_canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
return _canExecute;
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
_action();
}
}
我在 MainViewModel.cs 中使用 CommandHandler 的示例
private ICommand addNewUser_Command;
public ICommand AddNewUser_Command
{
get
{
return addNewUser_Command ?? (addNewUser_Command = new CommandHandler(() => AddNewUser_Execute(), true));
}
}
【问题讨论】:
-
只保留一个类中继命令。无需保留其他类。将其保持在内部或公开状态取决于您的使用模式。如果您想将中继命令保留在不同的程序集中,请将其公开,如果它位于存在 VM 的同一程序集中,请将其设为内部
-
@SatyakiChatterjee 在 RelayCommand.cs 代码块内的两个类有什么区别?我注意到一个类以
结尾,而另一个则没有。一个比另一个有什么好处?我是否发现省略一个而只保留另一个?最后,无论我决定保留哪一个,我如何使用它并使用 can execute 控制它的启用或禁用。 -
那么以
结尾的类是泛型类,而以 object 结尾的类不是泛型类。最好将类与 一起使用。使用 T 您可以使用任何使您的类更通用的类型。但是对于对象,您只能使用对象。我会要求你看看 c# 泛型.. 不管怎样,用 one -
你的意思是我只能使用对象?您的意思是我使用中继命令的每个团队都必须将对象传递给它吗?即使我不需要?
-
Action
指向返回类型为 void 并接受一个参数的方法。 T 表示泛型类型。您可以传递字符串、对象、自定义类甚至 null(如果您不需要任何特定情况的参数)。请查看有关泛型、动作和谓词的文档