Возможно, самое длинное название вопроса за все время! Потому что это вопрос из двух частей.Как NotifyOnValidationError в конечном итоге вызывает CanExecute (и почему он не работает с MVVM Light RelayCommand)
(1) Я не понимаю, как настройка NotifyOnValidationError = «True» может инициировать обновления для моего CanExecute. Здесь есть немного волшебства, которые мне нужно понять. Кто-то (предмет) подписывается на событие CanExecuteChanged моей ICommand, но стек вызовов указывает на внешний код, поэтому я не могу понять, что происходит.
(2) Возможно, наиболее важные последующие вопросы: почему это не работает в MVVM Light RelayCommand! CanExecute вызывается только один раз при инициализации, а затем никогда больше. Глядя на исходный код RelayCommand в MVVM Light, он не выявляет каких-либо различий в сравнении с моей собственной реализацией. Я должен упомянуть, что делегат-делегат Призма, похоже, тоже не работает.
(Bonus) Maybee Я приближаюсь к этой проблеме неправильно? Я просто хочу включить/отключить кнопки на основе отказов проверки.
XAML (фрагмент):
<TextBox Grid.Column="1" Grid.Row="0">
<Binding Path="X" UpdateSourceTrigger="PropertyChanged" NotifyOnValidationError="True">
<Binding.ValidationRules>
<ExceptionValidationRule></ExceptionValidationRule>
</Binding.ValidationRules>
</Binding>
</TextBox>
<Button Grid.Column="1" Grid.Row="3" Command="{Binding CalculateCommand}">
Calculate
</Button>
RelayCommand:
public class MyRelayCommand : ICommand
{
readonly Action<object> Execute_;
readonly Predicate<object> CanExecute_;
public MyRelayCommand(Action<object> Execute, Predicate<object> CanExecute)
{
if (Execute == null)
throw new ArgumentNullException("No action to execute for this command.");
Execute_ = Execute;
CanExecute_ = CanExecute;
}
public bool CanExecute(object parameter)
{
return (CanExecute_ == null) ? true : CanExecute_(parameter);
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void Execute(object parameter)
{
Execute_(parameter);
}
}
ViewModel:
private DelegateCommand _calculateCommmand;
public DelegateCommand CalculateCommand
{
get
{
return _calculateCommmand ?? (_calculateCommmand = new DelegateCommand(
() =>
{
Sum = X + X;
},
() =>
{
try
{
Convert.ChangeType(X, TypeCode.Byte);
return true;
}
catch
{
return false;
}
}));
}
}
PS: Если вы хотите купить мой X + X программы, когда это делается по электронной почте я на [email protected]
Я должен отметить, что моя реализация представляет собой урезанный вариант источника, найденного для RelayCommand (MVVM Light), который находится здесь: https://mvvmlight.codeplex.com/SourceControl/latest#GalaSoft.MvvmLight/GalaSoft.MvvmLight (PCL)/Command/RelayCommand. cs Как вы можете видеть, он также использует CommandManager. – sunefred
Вот что я пытался вам сказать. Магия, которую вы просили, выполняется CommandManager. Я предполагаю, что ваш ViewModel реализует 'INotifyPropertyChanged', поэтому должен существовать' event PropertyChangedEventHandler PropertyChanged', который вы можете вызвать: 'PropertyChanged? .Invoke()'. Это говорит диспетчеру команды, что ему нужно снова вызвать ваши команды «CanExecute()». Попробуй! –