Nastavenie
Predpokladajme nasledujúce. Máme nasledujúce teoretické viewmodel trieda pre 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)
}
Okrem toho:
- Aktuálna trieda implementuje správne
INotifyPropertyChanged
- Všetky triedy v členských prístup reťaze správne náradie
INotifyPropertyChanged
(napr. dokument viewmodel prístupné zActiveDocument
nehnuteľnosť) ActiveDocument
môže byťnull
.ActiveDocument.Highlighting
môže mať hodnotu null.
Problém
Rád by som sa dostal príkaz, aby sa zapnutá len vtedy, keď stave, v komentára je splnené.
Možnosť bez RX
Napísal som moje vlastné knižnice na manipuláciu takýchto situáciách. Riešenie by byť buď:
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)
}
Alebo - ak chcete, kód byť trochu viac čitateľné, tak, že čiastočné podmienky by mohli byť znovu použité - ako to, že:
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)
}
Čo moja knižnica (alebo, presnejšie, LambdaCondition
trieda) robí, je:
- Sleduje všetky inštancie vykonávacie
INotifyPropertyChanged
a rukoväť zmeny (napr. priActiveDocument
zmeny aleboActiveDocument.Highlighting
zmeny aleboActiveDocument.Highlighting.Type
zmeny atď.) - To udržuje prehľad možných
null
s na spôsob, ako v takom prípade sa vráti na predvolenú hodnotu (v tomto prípade,false
) - Automaticky hlási zmeny (ale len zmeny) dostupnosti na príkaz, tak, že UI môže byť obnovené, keď je to potrebné.
Otázka
Ako by sa realizovať scenár popísaný vyššie pomocou System.Reactive
v C#? Je to možné urobiť jednoducho pri zachovaní všetkých požiadaviek o INotifyPropertyChanged
, nepovoľuje hodnoty null na ceste a predvolenú hodnotu? Môžete mať akýkoľvek rozumný predpoklady, keď je to potrebné.