Связывание WPF CommandParameter и canExecute - PullRequest
6 голосов
/ 17 ноября 2009

У меня есть шаблон для элемента 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>

В качестве DataContext у меня есть сущность linq с идентификатором, а не с нулевым полем.

Проблема заключается в следующем: если я использую DelegateCommand 'Добавить' с CanExecutedMethod:

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

вызывается только один раз, а параметр имеет значение null (в то время как textBlock показывает правильное значение идентификатора). CanExecute вызывается до вызова свойства ID (проверяется с помощью отладчика). Похоже, что до привязки к фактическому параметру wpf вызывает canExecute и забывает об этом. После завершения привязки и загрузки правильного значения он больше не вызывает CanExecute.

В качестве обходного пути я могу использовать команду только с исполняемым делегатом:

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

AddExecute вызывается с правильным значением идентификатора и работает отлично. Но я все еще хочу использовать функциональность CanExecute. Есть идеи?

Ответы [ 3 ]

4 голосов
/ 14 октября 2011

В этом случае лучше вызывать RaiseCanExecuteChanged () для свойства, используемого в качестве параметра для команды. В вашем случае это будет свойство ID в вашей ViewModel (или в зависимости от того, какой DataContext вы используете).

Было бы что-то вроде этого:

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

Эффект будет таким же, как и у вашего решения, но он не позволяет использовать логику команд из кода.

2 голосов
/ 17 ноября 2009

Можно попытаться использовать CommandManager.InvalidateRequerySuggested для принудительного обновления.

1 голос
/ 04 января 2015

Я использую параметр как object, а затем возвращаю его к int.

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

и в методе добавления

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

    //or simply

    int id2 = (int)parameter;

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