wpf - 将 DelegateCommand 注册到 CompositeCommand 的最佳实践

标签 wpf mvvm prism composition

iv'e 在我的启动项目中全局公开了一个 CompositeCommand

 public static class Commands
 {
      public static readonly CompositeCommand DiceRolledCommand = new CompositeCommand();
 }

在我的启动项目引用的 ControlLibrary 中,我有一个 Control 有一个 DelegateCommand , 此控件的每个实例都必须使用全局公开的 DiceRolledCommand 注册它的命令。

这样做的最佳做法是什么:

这里有 3 个想法,其中前 2 个我不喜欢,因为它们有点骇人听闻,您采用一些编程组件 (dp) 并为了您的利益而改变它的用途,导致代码和设计不佳。


1) CompositeCommand 类型的常规 decadency 属性,将使用 DiceRolledCommand 设置 并在其 CallBack 上注册 MyControl 的 DelegateCommand (OnDiceRolledCommand) 。

public class MyControl : Control 
{
    public DelegateCommand<Tuple<int, int>> OnDiceRolledCommand { get; private set; }

    public CompositeCommand GlobalDiceRolledCommand
    {
        get { return (CompositeCommand)GetValue(GlobalDiceRolledCommandProperty); }
        set { SetValue(GlobalDiceRolledCommandProperty, value); }
    }

    public static readonly DependencyProperty GlobalDiceRolledCommandProperty =
        DependencyProperty.Register("GlobalDiceRolledCommand", typeof(CompositeCommand), typeof(MyControl), new UIPropertyMetadata(null,GlobalDiceRolledCommandPropertyChanged));

    private static void GlobalDiceRolledCommandPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var myControl= d as MyControl ;
        var compoisteCommand = e.NewValue as CompositeCommand;
        compoisteCommand.RegisterCommand(myControl.OnDiceRolledCommand);            
    }         
}


 <local:MyControl GlobalDiceRolledCommand="{x:Static local:Commands.DiceRolledCommand}"/>

我不喜欢这种方法,因为它是一种操作,其中使用的依赖属性具有复杂的逻辑 setter 。


2) 我也可以做与 (1) 中相同的操作,使用带有附加属性的第三方类,该类将在附加属性的 CallBack 中注册 OnDiceRolledCommand

public static class Commands
{
     public static readonly CompositeCommand DiceRolledCommand = new CompositeCommand(); 

     public static ICommand GetRegisterToDiceRolledCommand(DependencyObject obj)
    {
        return (ICommand)obj.GetValue(RegisterToDiceRolledCommandProperty);
    }

    public static void SetRegisterToDiceRolledCommand(DependencyObject obj, ICommand value)
    {
        obj.SetValue(RegisterToDiceRolledCommandProperty, value);
    }

    public static readonly DependencyProperty RegisterToDiceRolledCommandProperty =
        DependencyProperty.RegisterAttached("RegisterToDiceRolledCommand", typeof(ICommand), typeof(Commands), new UIPropertyMetadata(null,OnRegisterToDiceRolledCommandProperty);

    private static void OnRegisterToDiceRolledCommandProperty(DependencyObject d , DependencyPropertyChangedEventArgs e)
    {
        var commandToRegister = e.newValue as DelegateCommand;
        DiceRolledCommand.RegisterCommand(commandToRegister );
    }
}

<local:MyContorl local:Commands.RegisterToDiceRolledCommand="{Binding OnDiceRolledCommand , RelativeSource={RelativeSource Self}}"/>

出于与 1 .. 相同的原因,我也不喜欢这种方法


3) 将复合命令作为参数传递给构造函数,这种方法更好,因为它保持 构造函数中的初始化逻辑应该在什么地方,我只是不知道如何传递 通过 XAML 与承包商的争论,我不确定这是否可能。

 public class MyControl : Control 
 {
      public MyControl(CompositeCommand globalDiceRolledCommand)
      {
          .........
          globalDiceRolledCommand.Register(OnDiceRolledCommand); 
      }
 }  

 <local:MyControl ..... > 
    Some how pass parameters to contractor in order to create the element in XAML  
 </local:MyControl>

总结:

A) 关于 (1) 和 (2) 的任何想法。

B) 关于如何完成 3 的想法,以及它是否看起来不错的设计。

C) 完成此场景的任何良好模式。

提前致谢。

最佳答案

每当我使用这样的全局命令时,它们通常在每个库都可以引用的基础结构类库中定义。或者它们在每个模块都可以直接引用的消费核心库中定义。

我在 Code Project article 中写了很多这样的东西 Part 2 here

关于wpf - 将 DelegateCommand 注册到 CompositeCommand 的最佳实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15735830/

相关文章:

c# - "Assembly is not referenced by this project"WPF资源字典错误

c# - 通过数据库使用 ViewModel 填充 DataGrid

c# - WPF : Assigning to RichTextBox. 文档极慢(7 分钟!)

wpf - 如何使用 WPF 进行日志记录?

c# - 如何获取记事本文件保存位置

java - 存储库和Viewmodel之间的数据

mvvm - 测试 ViewState 的 PublishSubject

c# - 在 XAML 中从 DependecyProperty 绑定(bind)到 DataContext (ViewModel)

wpf - 在 Prism 中使用 ModuleManager 加载模块

wpf - Prism 7.0 RegisterSingleton 不工作?