将命令 属性 添加到任何自定义控件

Add command property to any custom controls

我可以使用以下代码导航到另一个视图。我想使用 tabControl 和自定义控件进行导航,但没有用于绑定 myCommand 的命令 属性。 那么如何将我的命令绑定到自定义控件?:

<Button Command="{Binding myCommand}" Content="Nav"/>

1.Is还有绑定的吗?
2.how 我可以将命令 属性 添加到自定义控件吗?

自定义控件和用户控件

为命令创建 DependencyProperty

public class MyControl : Control
{
    static MyControl()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(MyControl), new FrameworkPropertyMetadata(typeof(MyControl)));
    }

    public ICommand Command
    {
        get { return (ICommand)GetValue(CommandProperty); }
        set { SetValue(CommandProperty, value); }
    }

    public static readonly DependencyProperty CommandProperty = DependencyProperty.Register(
        "Command",
        typeof(ICommand),
        typeof(MyControl),
        new PropertyMetadata(null, OnCommandPropertyChanged));

    private static void OnCommandPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        MyControl control = d as MyControl;
        if (control == null) return;

        control.MouseLeftButtonDown -= OnControlLeftClick;
        control.MouseLeftButtonDown += OnControlLeftClick;
    }

    private static void OnControlLeftClick(object sender, MouseButtonEventArgs e)
    {
        MyControl control = sender as MyControl;
        if (control == null || control.Command == null) return;

        ICommand command = control.Command;

        if (command.CanExecute(null))
            command.Execute(null);
    }
}

xaml:

<local:MyControl Command="{Binding SomeCommand}"/>

其他控件

创建附加行为。

public static class ExecutesCommandOnLeftClickBehavior
{
    public static ICommand GetCommand(DependencyObject obj)
    {
        return (ICommand)obj.GetValue(CommandProperty);
    }

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

    public static readonly DependencyProperty CommandProperty = DependencyProperty.RegisterAttached(
        "Command",
        typeof(ICommand),
        typeof(ExecutesCommandOnLeftClickBehavior),
        new PropertyMetadata(null, OnCommandPropertyChanged));

    private static void OnCommandPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        UIElement element = d as UIElement;
        if (element == null) return;

        element.MouseLeftButtonDown -= OnMouseLeftButtonDown;
        element.MouseLeftButtonDown += OnMouseLeftButtonDown;
    }

    private static void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        UIElement element = sender as UIElement;
        if (element == null) return;

        ICommand command = GetCommand(element);
        if (command == null) return;

        if (command.CanExecute(null))
            command.Execute(null);
    }
}

xaml:

<Grid local:ExecutesCommandOnLeftClickBehavior.Command="{Binding SomeCommand}"/>

您可以将事件更改为 MouseLeftButtonDown 以外的事件,如果需要,请为 CommandParameter 添加 DependencyProperty (AttachedProperty)。

每个 UIElement 都有所谓的 InputBindings

Input bindings support the binding of commands to input devices. For example, MouseBinding implements input bindings that include properties that are particular to mouse devices.

<Label Content="new">
    <Label.InputBindings>
        <MouseBinding Gesture="LeftClick" 
                      Command="{Binding Path=myCommand}" 
                      CommandParameter="smth"/>
    </Label.InputBindings>
</Label>

因此,与其注册新的命令和命令参数 DP 并处理事件以触发命令,不如尝试使用开箱即用的功能

添加到@djomlastic 的回答,以防有人想用命令发送参数。

创建新的依赖项属性,

public object CommandParameter
    {
        get { return (object)GetValue(CommandParameterProperty); }
        set { SetValue(CommandParameterProperty, value); }
    }

    public static readonly DependencyProperty CommandParameterProperty = DependencyProperty.Register(nameof(CommandParameter), typeof(object)
                                                                               , typeof(<ClassName>), new PropertyMetadata(string.Empty));

并在调用执行时将 CommandParameter 对象作为参数而不是 null 发送,

 private static void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    UIElement element = sender as UIElement;
    if (element == null) return;

    ICommand command = GetCommand(element);
    if (command == null) return;

    if (command.CanExecute(element.CommandParameter))
        command.Execute(element.CommandParameter);
}