Konfiguracja
Załóżmy następujący. Mamy następujący teoretyczny klasa viewmodel dla aplikacji WPF:
public MyViewModel
{
public MyViewModel()
{
// Condition under which this command may be executed is:
// this.ActiveDocument.Highlighting.Type == Highlighting.Xml &&
// !this.ActiveDocument.IsReadOnly &&
// (this.License.Kind == LicenseKind.Full || this.License.TrialDay < 30)
MyCommand = new Command(obj => DoSomething());
}
public ICommand MyCommand { get; }
// (all other required properties)
}
W dodatku:
- Aktualny klasa realizuje poprawnie
INotifyPropertyChanged
- Wszystkie klasy w łańcuchu dostępu uczestników są realizowane zgodnie z oczekiwaniami
INotifyPropertyChanged
(na przykład, model prezentacji dokumentu, dostępny zActiveDocument
intelektualna) ActiveDocument
może byćnull
.ActiveDocument.Highlighting
również może być zerowa.
Problem
Chciałbym, aby drużyna była włączona tylko w przypadku spełnienia określonych warunków w komentarzu.
Opcja bez RX
Napisałem własną bibliotekę do obsługi takich sytuacji. Rozwiązaniem byłoby albo:
public MyViewModel
{
private readonly Condition commandAvailableCondition;
public MyViewModel()
{
commandAvailableCondition = new LambdaCondition(this,
vm => m.ActiveDocument.Highlighting.Type == Highlighting.Xml &&
!vm.ActiveDocument.IsReadOnly &&
(vm.License.Kind == LicenseKind.Full || vm.License.TrialDay < 30),
false);
MyCommand = new AppCommand(obj => DoSomething(), commandAvailableCondition);
}
public ICommand MyCommand { get; }
// (all other required properties)
}
Lub - jeśli chcesz, aby kod był trochę bardziej czytelny, aby częściowe warunki można było użyć ponownie - tak:
public MyViewModel
{
private readonly Condition commandAvailableCondition;
public MyViewModel()
{
var highlightingIsXml = new LambdaCondition(this,
vm => vm.ActiveDocument.Highlighting.Type == Highlighting.Xml,
false);
var documentIsReadonly = new LambdaCondition(this,
vm => vm.ActiveDocument.IsReadOnly,
false);
var appIsLicensed = new LambdaCondition(this,
vm => vm.License.Kind == LicenseKind.Full || this.License.TrialDay < 30,
false);
commandAvailableCondition = highlightingIsXml & !documentIsReadonly & appIsLicensed;
MyCommand = new AppCommand(obj => DoSomething(), commandAvailableCondition);
}
public ICommand MyCommand { get; }
// (all other required properties)
}
Że moja biblioteka (lub, dokładniej LambdaCondition
klasa) sprawia, że jest to:
- Śledzi wszystkie wystąpienia, które implementują
INotifyPropertyChanged
i przetwarzać zmiany (na przykład. kiedyActiveDocument
zmiany lubActiveDocument.Highlighting
zmiany lubActiveDocument.Highlighting.Type
zmiany itp.) - Śledzi możliwe
null
s w drodze, i w tym przypadku zwróci wartość domyślna (w tym przypadku,false
) - Automatycznie informuje zespół o zmianach (ale tylko o zmianach) dostępności, aby w razie potrzeby można było zaktualizować interfejs użytkownika.
Pytanie
Jak można było zrealizować scenariusz opisany powyżej, przy użyciu System.Reactive
w C#? Czy można to zrobić łatwo, zachowując wszystkie wymagania INotifyPropertyChanged
, zera na drodze i wartość domyślna? Można robić wszelkie uzasadnione przypuszczenia, gdy jest to konieczne.