WPF中使用System.Windows.Interactivity实现事件绑定的替代方法
一、问题描述
对于 Button
等控件,在 MVVM
中我们能通过 Command
绑定解决 Click
事件。具体如下所示:
<Button Margin="10" Height="50" Content="Clear" Command="{Binding Path=Clear}"></Button>
对于TextChanged
、MouseMove
等事件可以借助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
命令,并能也将对应参数也发送至该命令!