prism InvokeCommandAction行为忽略IsEnabled属性(可能的bug?)

时间:2014-10-15 08:47:48

标签: c# prism

我试图找到使用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上的属性。我把这个例子简化为最基本的元素。然而,这是一种非常特殊的奇怪行为,我肯定在这里做错了什么?这不可能是棱镜中的一个错误吗?

2 个答案:

答案 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。