Невозможно привязать ICommand в виртуальной машине к кнопке Command в xaml
Я создаю виртуальную машину на основе легкого инструментария MVVM. В ВМ есть простой ICommand(RelayCommand)
private RelayCommand _myCommand = null;
public RelayCommand MyCommand
{
get
{
if (_myCommand == null) //set break point here for debug
{
_myCommand = new RelayCommand(() =>
{
try
{
//....
}
catch (Exception ex)
{
// notify user if there is any error
//....
}
}
, () => true);
}
return _myCommand;
}
}
затем в xaml просто свяжите это свойство Command с такой кнопкой:
<Button Grid.Column="1" x:Name="Test" Content="Test" Margin="2,0,2,0" Command="{Binding Path=MyCommand}" />
Затем запустите приложение и нажмите на кнопку, ответа нет вообще. Нет ошибок. ВМ работает нормально. Данные были загружены в сетку данных до того, как я нажму кнопку "Тест".
Если отладить приложение и поставить точку останова, точка никогда не будет достигнута.
Как решить эту проблему?
4 ответа
Работает на моей машине:)
Серьезно, я сделал простой проект, создал ViewModel, вставил в ваш код, и это сработало. Я предполагаю, что вы имеете дело с другой проблемой.
Время евангелизировать немного
Этот код ViewModel пахнет. Вы можете подумать об использовании какой-то MVVM-инфраструктуры или помощников. Например, если вы посмотрите на ViewModelSupport, вы можете написать свою ViewModel следующим образом:
public class MyViewModel : ViewModelBase
{
public void Execute_MyCommand()
{
// Your execution code here
}
}
Тогда вы избегаете всей этой грязной сантехники. Просто подумай об этом:)
Добавьте сеттер в ваше свойство MyCommand.
Как всегда, проверьте окно вывода на наличие ошибок привязки данных при визуализации XAML.
Кроме того, попробуйте добавить конвертер тестовых значений и поместить точку останова в метод convert, чтобы увидеть, выполняется ли привязка данных даже для этой команды. Если точка останова не достигнута, вы знаете, что у вас есть проблема в вашем XAML. Если достигнута точка останова, посмотрите на значение, чтобы увидеть, является ли контекст данных правильным.
<UserControl.Resources>
<ResourceDictionary>
<TestConverter x:Key="TestConverter" />
</ResourceDictionary>
<Button Grid.Column="1" x:Name="Test" Content="Test" Margin="2,0,2,0" Command="{Binding Path=MyCommand, Converter={StaticResource TestConverter}}" />
</UserControl>
Конвертер тестовых значений - очень полезен для устранения проблем с привязкой данных.
public class TestConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
Debug.WriteLine("TestConverter.Convert(value := {0}, targetType := {1}, parameter := {2}, culture := {3})",
value, targetType, parameter, culture);
return value; // put break point here to test data binding
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
Debug.WriteLine("TestConverter.ConvertBack(value := {0}, targetType := {1}, parameter := {2}, culture := {3})",
value, targetType, parameter, culture);
return value;
}
}
1) Убедитесь, что вы возвращаетесь true
от реле команды CanExecute
делегировать. (Я вижу, что вы делаете это, но хорошо, чтобы перепроверить).
2) Кнопка внутри ListBox
, DataGrid
или же DataForm
?
Для ListBox или DataGrid:
В этом случае вам нужно изменить выражение привязки, чтобы оно ссылалось на VM DataContext, а не на элемент с привязкой к данным. Смотрите этот ответ.
Для DataForm:
Более сложно, но посмотрите на этот вопрос.
Код выглядит нормально. так что вам просто нужно проверить окно вывода на наличие ошибок привязки данных. возможно, вы не установили правильный текст данных для представления. Кстати, вы должны добавить свою точку останова в try-catch команды.