Vielleicht der längste Fragetitel aller Zeiten! Weil das eine zweiteilige Frage ist.Wie kann NotifyOnValidationError CanExecute aufrufen (und warum funktioniert es nicht mit MVVM Light RelayCommand)
(1) Ich verstehe nicht, wie Einstellung NotifyOnValidationError = "True" kann Updates für meine CanExecute auslösen. Hier ist ein bisschen Magie involviert, die ich verstehen muss. Jemand (Sache) abonniert das Ereignis CanExecuteChanged von meinem ICommand, aber der Aufruf-Stack zeigt auf External-Code, so dass ich nicht herausfinden kann, was vor sich geht.
(2) Vielleicht die wichtigsten Follow-up-Fragen ist: Warum funktioniert es nicht in MVVM Light RelayCommand! Der CanExecute wird nur einmal bei der Initialisierung und dann nie wieder aufgerufen. Wenn ich den Quellcode für RelayCommand in MVVM Light ansehe, ergeben sich im Vergleich zu meiner eigenen Implementierung keine Chocking-Unterschiede. Ich sollte erwähnen, dass Prism's DelegateCommand auch nicht zu funktionieren scheint.
(Bonus) Maybee Ich nähere mich diesem Problem auf die falsche Art? Ich möchte im Grunde Schaltflächen basierend auf Validierungsfehlern aktivieren/deaktivieren.
XAML (Snippet):
<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);
}
}
Ansichtsmodell:
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: Wenn Sie kaufen wollen mein X + X-Programm, wenn es geschieht, E-Mail ich bei [email protected]
ich, dass meine Implementierung mag darauf hinweisen, ist eine abgespeckte Variante der Quelle gefunden für RelayCommand (MVVM Light), hier gefunden: https://mvvmlight.codeplex.com/SourceControl/latest#GalaSoft.MvvmLight/GalaSoft.MvvmLight (PCL)/Command/RelayCommand. cs Wie Sie sehen können, verwendet es auch den CommandManager. – sunefred
Das wollte ich dir sagen. Die Magie, nach der Sie gefragt haben, wird vom CommandManager erledigt. Ich nehme an, Ihr ViewModel implementiert 'INotifyPropertyChanged', daher muss ein 'event PropertyChangedEventHandler PropertyChanged' vorhanden sein, das Sie aufrufen können:' PropertyChanged? .Invoke() '. Dies teilt dem Command Manager mit, dass er die Befehle '' CanExecute() 'erneut aufrufen muss. Versuch es! –