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

时间:2013-03-31 23:39:50

标签: wpf mvvm prism composition

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

 public static class Commands
 {
      public static readonly CompositeCommand DiceRolledCommand = new CompositeCommand();
 }
在我的启动项目引用的ControlLibrary中的

我得到了一个具有DelegateCommand的Control, 此Control的每个实例都必须使用全局公开的DiceRolledCommand注册它的Command。

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

这里有3个想法,其中前两个我不喜欢,因为它们是一种黑客,你需要一些编程组件(dp)并改变它的用途,从而导致代码和设计不佳。 / p>


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}"/>

我不喜欢这种方法,因为它是一种使用Dependency属性具有复杂逻辑设置器的操作。


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)完成此方案的任何良好模式。

提前谢谢。

1 个答案:

答案 0 :(得分:2)

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

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