【问题标题】:Implementation of Command pattern in WPFWPF中命令模式的实现
【发布时间】:2017-02-20 23:02:51
【问题描述】:

假设我不允许使用默认的 wpf 类 RoutedCommand、CommandBinding 和 ICommand 接口。相反,我必须提供我自己的实现。 所以我指定了简单的 ICommand 接口:

public interface ICommand
{
    void Execute();
}

为特定命令创建一个类:

public class NewCommand : ICommand
{
    private readonly IReceiver _receiver;
    // receiver is any class that provides implementation of a New() method

    public NewCommand(IReceiver receiver)
    {
        _receiver = receiver;
    }
    public void Execute()
    {
        _receiver.New();
    }
}

还必须有一个 Invoker:

public class Invoker
{
    private ICommand _command;
    public void SetCommand(ICommand c)
    {
        _command = c;
    }
    public void Run()
    {
        _command.Execute();
    }
}

考虑到默认实现我的代码如下所示,我如何将这一切连接到 XAML:

public class DesignerCanvas : Canvas
{
    private readonly IDesignerCommandsReceiver _receiver;

    public DesignerCanvas()
    {
        _receiver = new DesignerCommandsReceiver(this);
        CommandBindings.Add(new CommandBinding(ApplicationCommands.New, New_Executed));
    }

    private void New_Executed(object sender, ExecutedRoutedEventArgs e)
    {
        _receiver.New();
    }
}

调用New命令的按钮绑定如下:

<Button Margin="3" Width="55" Style="{StaticResource ToolBarButtonBaseStyle}"
                    Command="{x:Static ApplicationCommands.New}"
                    CommandTarget="{Binding ElementName=MyDesigner}">
                <Button.Content>
                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="4*"/>
                            <RowDefinition Height="1*"/>
                        </Grid.RowDefinitions>
                        <Image Source="Images/GenericDocument.png" Width="45"/>
                        <TextBlock Grid.Row="1" Text="New" VerticalAlignment="Bottom" HorizontalAlignment="Center"/>
                    </Grid>
                </Button.Content>
            </Button>

如果 Command 属性需要实现 System.Windows.Input.ICommand 的类,我如何绑定我的 NewCommand 类?我在哪里创建 Invoker 的实例,设置 NewCommand 并运行它?一般来说,我对如何用我自己的模式替换默认实现有点困惑。欢迎任何建议。

【问题讨论】:

  • 这似乎没有意义。分配给 Button 的 Command 属性的对象必须实现 System.Windows.Input.ICommand
  • 也许我的自定义 ICommand 接口应该继承自 System.Windows.Input.ICommand ?或者有一个使用 Click 属性的解决方法?
  • “如果 Command 属性需要实现 System.Windows.Input.ICommand 的类,我如何绑定我的 NewCommand 类?”你不能。您必须将 Button 的 Command 属性设置为实现内置 ICommand 接口的对象。
  • 你当然可以附加一个调用一些自定义命令对象的 Click 事件处理程序,但是出于什么原因呢?如果您的自定义 ICommand 接口继承 System.Windows.Input.ICommand,那么您的 ICommand 实现显然也会实现 System.Windows.Input.ICommand。那么为什么要自定义 ICommand 呢?
  • 忽略它是否有意义的问题,您可以创建一个附加属性,该属性使用您的自定义 ICommand 作为类型,并在其 PropertyChangedCallback 中附加一个 ButtonBase.Click 处理程序。

标签: c# wpf


【解决方案1】:

虽然我怀疑拥有自定义命令接口和实现是否真的有意义,但您可能可以创建一个自定义附加的Command 属性,它在其 PropertyChangedCallback 中附加一个Click 处理程序。 Click 处理程序将执行自定义命令。

以下代码示例声明了一个自定义ICustomCommand 接口,并在静态CustomCommandEx 类中声明了一个附加的Command 属性。

public interface ICustomCommand
{
    void Execute();
}

public static class CustomCommandEx
{
    public static readonly DependencyProperty CommandProperty =
        DependencyProperty.RegisterAttached(
            "Command",
            typeof(ICustomCommand),
            typeof(CustomCommandEx),
            new PropertyMetadata(CommandPropertyChanged));

    public static ICustomCommand GetCommand(DependencyObject obj)
    {
        return (ICustomCommand)obj.GetValue(CommandProperty);
    }

    public static void SetCommand(DependencyObject obj, ICustomCommand value)
    {
        obj.SetValue(CommandProperty, value);
    }

    private static void CommandPropertyChanged(
        DependencyObject obj, DependencyPropertyChangedEventArgs eventArgs)
    {
        var button = obj as ButtonBase;
        var command = eventArgs.NewValue as ICustomCommand;

        if (button != null)
        {
            button.Click += (s, e) => command.Execute();
        }
    }
}

您可以像这样分配附加属性:

<Button local:CustomCommandEx.Command="{Binding SomeCommand}"/>

其中SomeCommand 是视图模型中实现ICustomCommand 的属性。

【讨论】:

    猜你喜欢
    • 2017-12-06
    • 2011-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多