Loading

WPF 之事件绑定(八)

一、System.Windows.Interactivity 的使用

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

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

此时,当我们单击 Clear 按钮时,会执行 “Clear“ 命令。若我们需要传递参数,则使用 CommandParameter,如下所示传递:

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

那当我们使用 Button 的 其他事件,例如MouseMove 事件呢?甚至 TextBox 控件没有 Command 属性, 该如何使用 Command 呢?

这就需要我们通过 Nuget 添加 “System.Windows.Interactivity” 包后,引入如下命名控件:

 xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"

例如,我们实现一个 TextBox的 TextChanged事件,当文本内容发生变化,弹出踢提示信息:

  <TextBox  Height="50" VerticalContentAlignment="Center" Margin="10" BorderBrush="Black" >
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="TextChanged">
                    <i:InvokeCommandAction Command="{Binding DisplayMessage}"/>
                </i:EventTrigger>
            </i:Interaction.Triggers>
        </TextBox>

二、带事件参数(EventArgs)的事件绑定

​ 上面介绍的事件绑定并不足以应对所有的情况,因为很多情况下我们还需要从事件的EventArgs中获取数据,例如从MouseMove事件参数中获取鼠标位置和按键状态等。但InvokeCommandAction在未对CommandParameter绑定的情况下给Execute方法传递的参数为null。因此我们需要自己写一个类来处理事件到命令的绑定。自定义 EventCommand 如下所示:

  class EventCommand : TriggerAction<DependencyObject>
    {

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

        // Using a DependencyProperty as the backing store for Command.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty CommandProperty =
            DependencyProperty.Register("Command", typeof(ICommand), typeof(EventCommand), new PropertyMetadata(null));



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

        // Using a DependencyProperty as the backing store for CommandParameter.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty CommandParameterProperty =
            DependencyProperty.Register("CommandParameter", typeof(object), typeof(EventCommand), new PropertyMetadata(null));



        protected override void Invoke(object parameter)
        {
            if (CommandParameter != null)
            {
                parameter = CommandParameter;
            }
            Command?.Execute(parameter);
        }
    }

例如,我们要实现对一个 TextBox 鼠标位置信息的获取,具体绑定如下:

   <TextBox Height="150" Margin="10" Background="LightSteelBlue" Text="获取鼠标位置" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" >
          <i:Interaction.Triggers>
              <i:EventTrigger EventName="MouseMove">
                  <local:EventCommand Command="{Binding GetPositionCommand}"></local:EventCommand>
              </i:EventTrigger>
          </i:Interaction.Triggers>
        </TextBox>

如此,ViewModel 的绑定命令就可以收到事件参数了:

      public ICommand GetPositionCommand { get; set; }
        private void GetPositionCommandExecute(object obj)
        {
            var args = obj as MouseEventArgs;
            if (args != null)
            {
                var pos = args.GetPosition(args.Device.Target);
                CurrentPosition = new Position()
                {
                    X = pos.X,
                    Y = pos.Y,
                };
            }
        }
        public WindowVM()
        {
            _position = new Position();
            GetPositionCommand=new RelayCommand(GetPositionCommandExecute, null);
        }
posted @ 2021-02-09 13:51  Dwaynerbing  阅读(3390)  评论(0编辑  收藏  举报