wpf - best practice of registering a DelegateCommand to a CompositeCommand

岁酱吖の 提交于 2019-12-07 14:44:08

问题


iv'e got a CompositeCommand exposed globally in my startup project

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

in a ControlLibrary referenced by my startup project iv'e got a Control which has a DelegateCommand , each instance of this Control has to register it's Command with the globally exposed DiceRolledCommand.

what wold be the best practice of doing so :

here are 3 idea's of which the first 2 i don't like because they are a kinda of hack , where you take some programming component (dp) and alter it's use for your benefit , resulting in poor code and design .


1) a regular decadency property of type CompositeCommand which will be set with DiceRolledCommand and on it's CallBack register MyControl's 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}"/>

i don't like this approach since it's a kind of manipulation where a Dependency Property is used has a Complex logical setter .


2) i could also do the same as in (1) using a third party class with an attached property which will register the OnDiceRolledCommand in an attached property's CallBack

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

i also don't like this approach for the same reason as 1 ..


3) passing the composite command as a parameter to constructor , this approach is better since it keeps the initializing logic in the constructor where it should be , i just can't figure out how to pass an argument to a contractor through XAML , i'm not sure if it's even possible .

 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>

to summarize :

A) any thoughts about (1) and (2) .

B) thoughts of how to accomplish 3 , and if it seems like good design .

C) Any good pattern of accomplishing this scenario.

thanks in advance .


回答1:


Whenever I use Global Commands like that they are usually defined in either an Infrastructure class library which every library can reference. Or they are defined in a consuming core library that each module could reference directly.

I wrote a lot of this up in a Code Project article Part 2 here



来源:https://stackoverflow.com/questions/15735830/wpf-best-practice-of-registering-a-delegatecommand-to-a-compositecommand

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!