我有一个简单的设置,其中包含一个自动完成框和其Populating事件,我想将其绑定到一个命令。我使用
clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity
(有更好的命名空间来完成这个吗?)
绑定并不是什么大不了的事情,关键是将PopulatingEventArgs参数传递给绑定的命令。
那么我该如何按照PRISM的最佳实践和MVVM的一般惯例来做呢?
我有一个简单的设置,其中包含一个自动完成框和其Populating事件,我想将其绑定到一个命令。我使用
clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity
(有更好的命名空间来完成这个吗?)
绑定并不是什么大不了的事情,关键是将PopulatingEventArgs参数传递给绑定的命令。
那么我该如何按照PRISM的最佳实践和MVVM的一般惯例来做呢?
我尝试使用InteractiveCommand,但遇到了问题。相反,我设置了对Microsoft.Expression.Interactions的引用并包含了相关内容。
转换后:我尝试了InteractiveCommand,但是它给我带来了问题。相反,我设置了对Microsoft.Expression.Interactions的引用并包含了相关内容。
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
<i:Interaction.Triggers>
<i:EventTrigger EventName="AppointmentEditing">
<ei:CallMethodAction MethodName="AppointmentEditing" TargetObject="{Binding}" />
</i:EventTrigger>
<i:EventTrigger EventName="ShowDialog">
<ei:CallMethodAction MethodName="ShowDialog" TargetObject="{Binding}" />
</i:EventTrigger>
</i:Interaction.Triggers>
...在我的用户控件中。
接下来将事件处理程序放在我的视图模型中,并将作用域设置为公共:
public void ShowDialog(object sender, ShowDialogEventArgs e) {
}
public void AppointmentEditing(object sender, AppointmentEditingEventArgs e) {
}
目前工作良好。
我的解决方案似乎不理解
ShowDialogEventArgs`。我应该如何实现它? - KMarto没有内置的方法,这是我如何做的:
经典的交互触发器用法如下:
<Button Content="I am a button">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseEnter">
<i:InvokeCommandAction Command="{Binding CommandWithNoArgs}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
我们无法通过绑定访问MouseEnter
事件的EventArgs
,因此我们需要修改丢弃它的代码段。恰好,这个代码段是InvokeCommandAction
。TriggerAction<DependencyObject>
最基本的实现如下:public class InteractiveCommand : TriggerAction<DependencyObject>
{
protected override void Invoke(object parameter)
{
}
}
那个参数
就是你的EventArgs
!但是要注意,这并不简单,我们需要复制正常的InvokeCommandAction
的行为。通过反编译器Reflector,我对其进行了反编译(但你也可以查看官方源代码,我只是懒得去)。
我们将不关心CommandParameter
依赖属性,我们假设如果你使用这个而不是InvokeCommandAction
,则每次都想要EventArgs
。
以下是完整的类(仅适用于WPF,请参见EDIT以了解SilverLight):
public class InteractiveCommand : TriggerAction<DependencyObject>
{
protected override void Invoke(object parameter)
{
if (base.AssociatedObject != null)
{
ICommand command = this.ResolveCommand();
if ((command != null) && command.CanExecute(parameter))
{
command.Execute(parameter);
}
}
}
private ICommand ResolveCommand()
{
ICommand command = null;
if (this.Command != null)
{
return this.Command;
}
if (base.AssociatedObject != null)
{
foreach (PropertyInfo info in base.AssociatedObject.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance))
{
if (typeof(ICommand).IsAssignableFrom(info.PropertyType) && string.Equals(info.Name, this.CommandName, StringComparison.Ordinal))
{
command = (ICommand)info.GetValue(base.AssociatedObject, null);
}
}
}
return command;
}
private string commandName;
public string CommandName
{
get
{
base.ReadPreamble();
return this.commandName;
}
set
{
if (this.CommandName != value)
{
base.WritePreamble();
this.commandName = value;
base.WritePostscript();
}
}
}
#region Command
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(InteractiveCommand), new UIPropertyMetadata(null));
#endregion
}
同任何从互联网获取的代码一样,我强烈建议你阅读整个类并尝试理解它的作用。不要只是将其丢到您的应用程序中。
现在我们可以执行:
<Button Content="I am a button">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseEnter">
<local:InteractiveCommand Command="{Binding CommandWithEventArgs}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
然后是背后的代码:
#region CommandWithEventArgs
DelegateCommand<MouseEventArgs> _CommandWithEventArgs;
/// <summary>
/// Exposes <see cref="CommandWithEventArgs(MouseEventArgs)"/>.
/// </summary>
public DelegateCommand<MouseEventArgs> CommandWithEventArgs
{
get { return _CommandWithEventArgs ?? (_CommandWithEventArgs = new DelegateCommand<MouseEventArgs>(CommandWithEventArgs)); }
}
#endregion
public void CommandWithEventArgs(MouseEventArgs param)
{
}
完美收官;)
编辑:对于SilverLight,请改用以下代码:
public class InteractiveCommand : TriggerAction<DependencyObject>
{
protected override void Invoke(object parameter)
{
if (base.AssociatedObject != null)
{
ICommand command = Command;
if ((command != null) && command.CanExecute(parameter))
{
command.Execute(parameter);
}
}
}
#region Command
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(InteractiveCommand), new UIPropertyMetadata(null));
#endregion
}
请注意,这种方法不如使用完整版的 WPF 安全(不检查类型,可能会在冻结元素时崩溃)。