dongweian

一、问题描述

对于 Button 等控件,在 MVVM 中我们能通过 Command 绑定解决 Click 事件。具体如下所示:

    <Button Margin="10" Height="50" Content="Clear" Command="{Binding Path=Clear}"></Button>

对于TextChangedMouseMove等事件可以借助System.Windows.Interactivity文件后也可实现事件的绑定,具体描述见WPF 之事件绑定

那如何实现不使用System.Windows.Interactivity文件也实现此类事件的绑定呢?

答案是借助附加属性来完成

二、借助附加属性完成事件绑定

例如以TextChanged事件为例,我们首先申明一个附加属性TextBoxChangedCommand如下所示:

 public class AttachProperty
    {
        public static readonly DependencyProperty TextBoxChangedCommandProperty = DependencyProperty.RegisterAttached("TextBoxChangedCommand", typeof(ICommand), typeof(AttachProperty), new PropertyMetadata(OnTextBoxChangedCommandPropertyChangedCallback));

        [AttachedPropertyBrowsableForType(typeof(TextBox))]
        public static ICommand GetTextBoxChangedCommand(DependencyObject obj)
        {
            return (ICommand)obj.GetValue(TextBoxChangedCommandProperty);
        }

        public static void SetTextBoxChangedCommand(DependencyObject obj, ICommand value)
        {
            obj.SetValue(TextBoxChangedCommandProperty, value);
        }
        private static void OnTextBoxChangedCommandPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (d is TextBox textBox)
            {
                textBox.TextChanged += (sender, args) =>
                {
                    var command = (ICommand)textBox.GetValue(TextBoxChangedCommandProperty);
                    // 此处的参数发送,可以根据情况发送,例如需要文本内容,则返回textBox.Text。
                    command?.Execute(textBox.Text);
                };
            }
        }
    }

然后在在界面对应的ViewModel里面声明一个ICommand,具体如下:

  public class MainWindowVM
    {
        public ICommand TextCommand { get; set; }
        private void ExecuteTextCommand(object args)
        {
            MessageBox.Show($"数值变为:{args}");
        }

        public MainWindowVM()
        {
            TextCommand = new RelayCommand(ExecuteTextCommand);
        }
    }

在对应的界面上,将ViewModel里面的TextCommand命令属性绑定到附加属性上TextBoxChangedCommand,具体如下所示:

  <TextBox Height="100" Margin="20"
           local:AttachProperty.TextBoxChangedCommand="{Binding TextCommand, Mode=OneTime}"></TextBox>

如此即可实现当TextBox数值发生变化的时候,触发TextCommand命令,并能也将对应参数也发生至该命令!

分类:

技术点:

相关文章: