我试图找到使用prism InvokeCommandAction行为时忽略复选框的IsEnabled属性的原因。
基本上,如果我使用标准的InvokeCommandAction行为,那么一切正常,但如果我切换到棱镜InvokeCommandAction,则忽略IsEnabled属性。
为了复制这个,我从棱镜中取出了命令快速启动并将OrdersEditorView更改为:
<StackPanel Orientation="Vertical">
<ListView AutomationProperties.AutomationId="OrderListView" ItemsSource="{Binding Orders}" SelectionMode="Single" Width="Auto" Height="Auto" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="KeyUp">
<prism:InvokeCommandAction Command="{Binding ProcessOrderCommand}" TriggerParameterPath="Key"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<ListView.ItemTemplate>
<DataTemplate DataType="{x:Type models:OrderViewModel}">
<TextBlock Text="{Binding OrderName}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<CheckBox IsEnabled="False" Content="Prism" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="Checked">
<prism:InvokeCommandAction Command="{Binding ProcessOrderCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</CheckBox>
<CheckBox IsEnabled="False" Content="Interactivity">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Checked">
<i:InvokeCommandAction Command="{Binding ProcessOrderCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</CheckBox>
</StackPanel>
所以我只是将原始ListView包装在堆栈面板中,并添加了两个复选框,将现有的ProcessOrderCommand命令绑定到InvokeCommandAction行为。使用交互性InvokeCommandAction的复选框被正确禁用(IsEnabled属性被正确设置为False),但是启用了使用prism InvokeCommandAction的复选框,即使IsEnabled属性设置为false。
现在这只是一个基本的例子,在现实生活中,行为是将参数传递给命令(这就是我想使用prism版本的原因),并且IsEnabled属性绑定到ViewModel上的属性。我把这个例子简化为最基本的元素。然而,这是一种非常特殊的奇怪行为,我肯定在这里做错了什么?这不可能是棱镜中的一个错误吗?
答案 0 :(得分:2)
我知道这个问题有点旧,但今天我和同事在工作中遇到了同样的问题,所以我们确实要求StackOverflow,我们找不到解决方案。在我们解决之后,我们决定在此处发布解决方案,以防其他人在将来遇到此类问题。
正如@Georg Piwonka所说,这种行为是Prism设计的,但你可以使用你绑定的属性,在提升PropertyChanged事件之后,再调用命令的RaiseCanExecuteChanged方法来重新评估CanExecute方法你在创建命令时使用。
因此,假设您有包含ProcessOrderCommand命令(DelegateCommand)的OrderProcessingViewModel类
public class OrderProcessingViewModel
{
public DelegateCommand<KeyEventArgs> ProcessOrderCommand;
private string targetProperty;
public OrderProcessingViewModel()
{
ProcessOrderCommand = new DelegateCommand<KeyEventArgs>(ProcessOrder, CanProcessOrder);
}
private Order OrderToProcess { get; set; }
public string TargetProperty
{
get { return targetProperty; }
set
{
if (!Equals(targetProperty, value))
{
targetProperty = value;
OnPropertyChanged("TargetProperty");
//IMPORTANT: Let the delegate command to call its CanExecute method so we can update the Enabled property.
ProcessOrderCommand.RaiseCanExecuteChanged();
}
}
}
private bool CanProcessOrder(KeyEventArgs arg)
{
//TODO: Here you check when to enable or disable the check box
var mustEnable = OrderToProcess != null;
//The value returned from this method is the result assigned to the IsEnable property for the command's related object
return mustEnable;
}
private void ProcessOrder(KeyEventArgs obj)
{
//Do the stuff to process the order
}
}
这里的关键概念不是反对棱镜。如果要在目标属性更改时启用相关控件,则应重新运行DelegateCommand命令的CanExcecute方法。
Prism有一个用于此目的的机制,您唯一需要做的就是为ProcessOrderCommand命令调用RaiseCanExecuteChanged,如果方法的结果为true,则启用相关控件,在这种情况下将启用Checkbox。
答案 1 :(得分:1)
你做得对。 似乎行为是由棱镜InvokeCommandAction设计的。 prism InvokeCommandAction对DelegateCommand上的CanExecute方法进行cals,并使用此函数的返回值设置IsEnabled属性。所以上面的IsEnabled被忽略了。 Button Command Property中的行为相同,它根据Command的CanExecute方法设置IsEnabled。