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

时间:2017-12-16 20:27:20

标签: c# wpf mvvm icommand

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

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

1.无论如何要绑定?
2.如何将命令属性添加到自定义控件?

3 个答案:

答案 0 :(得分:2)

每个UIElement都有所谓的InputBindings

  

输入绑定支持将命令绑定到输入设备。例如,MouseBinding实现包含特定于鼠标设备的属性的输入绑定。

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

所以不是注册新的Command和CommandParameter DP并处理触发Command的事件,而是尝试使用开箱即用的功能

答案 1 :(得分:0)

CustomControls和UserControls

为命令创建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添加DependencyPropertyAttachedProperty)。

答案 2 :(得分:0)

添加到@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));

并在调用execute时发送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);
}