我正在使用来自AlexeyZakharov's weblog的类InvokeDelegateCommandAction,根据人们的一些建议,这是从EventTrigger将View中的参数发送回ViewModel的最佳方法。
这就是我所拥有的。
在视图中(特定的DataGrid):
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged" >
<cmnwin:InvokeDelegateCommandAction
Command="{Binding SelectedExcludedItemChangedCommand}"
CommandParameter="{Binding RelativeSource={RelativeSource self}, Path=SelectedItems}" />
</i:EventTrigger>
</i:Interaction.Triggers>
在ViewModel中:
public DelegateCommandWithParameter SelectedActiveItemChangedCommand
{
get
{
return selectedActiveItemChangedCommand ??
(selectedActiveItemChangedCommand = new DelegateCommandWithParameter(DoSelectedActiveItemsChanged, CanDoSelectedActiveItemsChanged));
}
}
public bool CanDoSelectedActiveItemsChanged(object param)
{
return true;
}
public void DoSelectedActiveItemsChanged(object param)
{
if (param != null && param is List<Object>)
{
var List = param as List<Object>;
MyLocalField = List;
}
}
允许我以args传递对象的新类型DelegateCommand:
public class DelegateCommandWithParameter : ICommand
{
#region Private Fields
private Func<object, bool> canExecute;
private Action<object> executeAction;
private bool canExecuteCache;
#endregion
#region Constructor
public DelegateCommandWithParameter(Action<object> executeAction, Func<object, bool> canExecute)
{
this.executeAction = executeAction;
this.canExecute = canExecute;
}
#endregion
#region ICommand Members
public bool CanExecute(object parameter)
{
bool temp = canExecute(parameter);
if (canExecuteCache != temp)
{
canExecuteCache = temp;
if (CanExecuteChanged != null)
{
CanExecuteChanged(this, new EventArgs());
}
}
return canExecuteCache;
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
executeAction(parameter);
}
#endregion
}
每当我的代码到达DoSelectedActiveItemsChanged时,arg总是为NULL ....我在这里是一个完整的doofus吗? CommandParamter在哪里链接到命令args? AKA,为什么视图没有回复命令?请帮忙。
答案 0 :(得分:3)
我用ListBox
代替了它,但我得到了相同的东西。以下情况很好,因为它传递CommandParameter
而不是invoke参数。那么为什么CommandParameter
null
?
protected override void Invoke( object parameter ) {
this.InvokeParameter = parameter;
if ( this.AssociatedObject != null ) {
ICommand command = this.ResolveCommand();
if ( ( command != null ) && command.CanExecute( this.CommandParameter ) ) {
command.Execute( this.CommandParameter );
}
}
}
CommandParameter
似乎无法正常工作,因为您的绑定将其设置为null
。 {RelativeSource Self}
解析为InvokeDelegateCommandAction
,但没有SelectedItems
属性。相反,使用此绑定:
CommandParameter="{Binding RelativeSource={RelativeSource AncestorType={x:Type ListBox}}, Path=SelectedItems}"
然后CommandParameter
将从SelectedItemCollection
传入ListBox
。
还有一个问题,你很快就会发现。 DoSelectedActiveItemsChanged()
的{{1}}将是param
的实例,而不是SelectedItemCollection
。
答案 1 :(得分:1)
我已经借助乔尔的观察解决了这个问题......对于那些可能感兴趣的人来说,这是怎么回事。虽然显然我已经将Joel正确地归功于正确答案,但将这些信息作为答案而不是编辑问题似乎是正确的。
我发现了通用的DelegateCommand,所以摆脱了DelegateCommandWithParameter
public ICommand SelectedObjectsChangedCommand
{
get
{
return selectedObjectsChangedCommand ??
(selectedObjectsChangedCommand = new DelegateCommand<MyType>(DoSelectedObjectsChangedCommand , CanDoSelectedObjectsChangedCommand ));
}
}
'Do'(执行方法)现在返回SelectionChangedEventArgs ...
public void DoSelectedObjectsChangedCommand(object param)
{
if (param != null && param is SelectionChangedEventArgs)
{
foreach (MyType object in ((SelectionChangedEventArgs)param).AddedItems.Cast<MyType>().ToList())
{
selectedObjects.Add(object);
}
foreach (MyType object in ((SelectionChangedEventArgs)param).RemovedItems.Cast<MyType>().ToList())
{
selectedObjects.Remove(object);
}
UpdateAllCanDos();
}
}
除了我的其他业务逻辑外,它还可以实现非常流畅和直观的用户体验。非常感谢所有答案者。我一直用NHibernate做WPF和MVVM只用了一个月而且我不禁承认SO社区正在以最好和最丰富的方式让我学习学习曲线。