在WPF

时间:2017-02-20 11:03:42

标签: c# wpf

让我们说我不允许使用默认的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();
    }
}

也必须有一个祈求者:

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并运行它?一般来说,我对如何用我自己的模式替换模式的默认实现有点困惑。欢迎任何建议。

1 个答案:

答案 0 :(得分:1)

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

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

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的属性。