WPF CommandParameter имеет значение NULL при первом вызове CanExecute - PullRequest
79 голосов
/ 03 декабря 2008

Я столкнулся с проблемой с WPF и командами, которые связаны с кнопкой внутри DataTemplate ItemsControl. Сценарий довольно прямой. ItemsControl привязан к списку объектов, и я хочу иметь возможность удалить каждый объект в списке, нажав кнопку. Кнопка выполняет команду, а команда заботится об удалении. CommandParameter привязан к объекту, который я хочу удалить. Таким образом, я знаю, что пользователь нажал. Пользователь должен иметь возможность удалять только свои «собственные» объекты, поэтому мне нужно выполнить некоторые проверки в вызове «CanExecute» команды, чтобы убедиться, что у пользователя есть необходимые разрешения.

Проблема в том, что параметр, переданный в CanExecute, имеет значение NULL при первом вызове - поэтому я не могу запустить логику для включения / отключения команды. Однако, если я включу его всегда, а затем нажму кнопку, чтобы выполнить команду, CommandParameter будет передан правильно. Это означает, что связывание с CommandParameter работает.

XAML для ItemsControl и DataTemplate выглядит следующим образом:

<ItemsControl 
    x:Name="commentsList"
    ItemsSource="{Binding Path=SharedDataItemPM.Comments}"
    Width="Auto" Height="Auto">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal">
                <Button                             
                    Content="Delete"
                    FontSize="10"
                    Command="{Binding Path=DataContext.DeleteCommentCommand, ElementName=commentsList}" 
                    CommandParameter="{Binding}" />
            </StackPanel>                       
         </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

Итак, как вы можете видеть, у меня есть список объектов комментариев. Я хочу, чтобы CommandParameter команды DeleteCommentCommand был привязан к объекту Command.

Итак, я думаю, мой вопрос: кто-нибудь сталкивался с этой проблемой раньше? CanExecute вызывается для моей команды, но в первый раз параметр всегда равен NULL - почему это так?

Обновление: Мне удалось немного сузить проблему. Я добавил пустой Debug ValueConverter, чтобы вывести сообщение, когда CommandParameter привязан к данным. Оказывается, проблема в том, что метод CanExecute выполняется до того, как CommandParameter будет привязан к кнопке. Я попытался установить CommandParameter перед командой (как предложено) - но он все еще не работает. Любые советы о том, как его контролировать.

Обновление 2: Есть ли способ определить, когда привязка "выполнена", чтобы я мог принудительно выполнить повторную оценку команды? Кроме того - это проблема, что у меня есть несколько кнопок (по одной для каждого элемента в ItemsControl), которые связаны с одним и тем же экземпляром объекта Command?

Обновление 3: Я загрузил репродукцию ошибки в мой SkyDrive: http://cid -1a08c11c407c0d8e.skydrive.live.com / self.aspx / Код% 20samples / CommandParameterBinding.zip

Ответы [ 15 ]

0 голосов
/ 22 сентября 2014

Рядом с Предложением Эд Болла при настройке CommandParameter до Команда , убедитесь, что ваш метод CanExecute имеет параметр объект тип.

private bool OnDeleteSelectedItemsCanExecute(object SelectedItems)  
{
    // Your goes heres
}

Надеюсь, это предотвратит трату огромного количества времени, которое я потратил, чтобы выяснить, как получить SelectedItems в качестве параметра CanExecute

0 голосов
/ 26 ноября 2009

Я зарегистрировал это как ошибку в WPF в .Net 4.0, так как проблема все еще существует в бета-версии 2.

https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=504976

0 голосов
/ 22 декабря 2008

commandManager.InvalidateRequerySuggested работает и для меня. Я полагаю, что следующая ссылка говорит о подобной проблеме, и M $ dev подтвердил ограничение в текущей версии, а командаManager.InvalidateRequerySuggested является обходным решением. http://social.expression.microsoft.com/Forums/en-US/wpf/thread/c45d2272-e8ba-4219-bb41-1e5eaed08a1f/

Что важно, это время вызова commandManager.InvalidateRequerySuggested. Это должно быть вызвано после уведомления о соответствующем изменении значения.

0 голосов
/ 04 декабря 2008

Привет, Джонас, не уверен, будет ли это работать в шаблоне данных, но вот синтаксис привязки, который я использую в контекстном меню ListView, чтобы получить текущий элемент в качестве параметра команды:

CommandParameter = "{Binding RelativeSource = {RelativeSource AncestorType = ContextMenu}, Path = PlacementTarget.SelectedItem, Mode = TwoWay}"

0 голосов
/ 04 декабря 2008

Это длинный выстрел. чтобы отладить это, вы можете попробовать:
- проверка события PreviewCanExecute.
- используйте snoop / wpf mole, чтобы заглянуть внутрь и посмотреть, что такое параметр команды.

НТН,

...