简体   繁体   English

WPF CommandParameter绑定和canExecute

[英]WPF CommandParameter binding and canExecute

I have a template for treeView item: 我有一个treeView项的模板:

<HierarchicalDataTemplate x:Key="RatesTemplate">
    <StackPanel Orientation="Horizontal">
                        <TextBlock Text="{Binding Path=ID}"/>
                        <Button CommandParameter="{Binding Path=ID}" 
                                Command="{Binding ElementName=CalcEditView, Path=DataContext.Add}">Add</Button>                            
    </StackPanel>
</HierarchicalDataTemplate>

As a DataContext I have linq entity with ID not null field. 作为DataContext,我有一个ID为非空字段的linq实体。

The problem is: if I use DelegateCommand 'Add' with CanExecutedMethod: 问题是:如果我使用CanExecutedMethod的DelegateCommand'Add':

AddRate = new DelegateCommand<int?>(AddExecute,AddCanExecute);

its called only once and parameter is null (while textBlock shows proper ID value). 它只调用一次,参数为null(而textBlock显示正确的ID值)。 CanExecute is called before ID property is called (checked with debugger). 在调用ID属性之前调用CanExecute(使用调试器检查)。 Seems like before binding to actual parameter wpf is invoking canExecute and forgets about it. 似乎在绑定到实际参数之前,wpf正在调用canExecute并忘记它。 Once binding finished and proper value loaded it doesn't call CanExecute again. 绑定完成并加载正确的值后,它不会再次调用CanExecute。

As a workaround I can use command with only execute delegate: 作为一种解决方法,我可以使用只有执行委托的命令:

Add = new DelegateCommand<int?>(AddExecute);

AddExecute is invoked with correct ID value and is working perfectly. 使用正确的ID值调用AddExecute并且工作正常。 But I still want to use CanExecute functionality. 但我仍然想使用CanExecute功能。 Any ideas? 有任何想法吗?

In this scenario, it's better to call the RaiseCanExecuteChanged() on the property used as a parameter for the Command. 在这种情况下,最好在用作Command参数的属性上调用RaiseCanExecuteChanged()。 In your case, it would be the ID property in your ViewModel (Or whichever DataContext you're using). 在您的情况下,它将是您的ViewModel中的ID属性(或者您正在使用的任何DataContext)。

It would be something like this: 它会是这样的:

private int? _id;
public int? ID
{
    get { return _id; }
    set
    {
        _id = value;
        DelegateCommand<int?> command = ((SomeClass)CalcEditView.DataContext).Add;
        command.RaiseCanExecuteChanged();
    }
}

The effect will be the same as your solution, but it keeps the Command logic out of code-behind. 效果与您的解决方案相同,但它使Command逻辑不受代码隐藏的影响。

您可以尝试使用CommandManager.InvalidateRequerySuggested强制更新。

I use parameter as object and then cast it back to int . 我使用参数作为object ,然后将其强制转换为int

Add = new DelegateCommand<object>(add, canAdd);

and in add method 并添加方法

void add(object parameter){
    int id = Convert.ToInt32(parameter);

    //or simply

    int id2 = (int)parameter;

    //...
    //  do your stuff
    //...
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM