Ako používať RX ovládať príkaz je dostupnosť v zložitej situácii?

0

Otázka

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é z ActiveDocument 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. pri ActiveDocument zmeny alebo ActiveDocument.Highlighting zmeny alebo ActiveDocument.Highlighting.Type zmeny atď.)
  • To udržuje prehľad možných nulls 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é.

c# mvvm system.reactive wpf
2021-11-23 15:15:48
1

Najlepšiu odpoveď

0

Na ReactiveUI rámec má ReactiveCommand trieda, ktorá sa používa IObservable<T> ak chcete obnoviť stav príkazu (t. j. zvýšiť CanExecuteChanged udalosť ICommand).

Prosím, pozrite si dokumenty pre príklad, ako ho použiť na ovládanie vykonateľnosti:

var canExecute = this.WhenAnyValue(
    x => x.UserName, x => x.Password,
    (userName, password) => 
        !string.IsNullOrEmpty(userName) && 
        !string.IsNullOrEmpty(password));

var command = ReactiveCommand.CreateFromTask(LogOnAsync, canExecute);
2021-11-24 14:52:33

To postupujte podľa INotifyPropertyChange realizátormi v majetku prístup reťazca? Má to tiež fungovať správne, ak niektorý z vlastností je null? Mohli by ste prosím, ukázať, ako moja konkrétny príklad bude vyzerať, keď realizované v RX?
Spook

WhenAnyValue sa vydávať novú hodnotu, keď niektorý z Username a Password vlastnosti rasises na PropertyChanged udalosti. Aký je váš konkrétny príklad presne? Čo ste to skúsiť?
mm8

Vedeli ste, prečítajte si celý môj otázku? Som prezentované presný stav, ktorý by mal byť sledoval: vm => m.ActiveDocument.Highlighting.Type == Highlighting.Xml && !vm.ActiveDocument.IsReadOnly && (vm.License.Kind == LicenseKind.Full || vm.License.TrialDay < 30), Čo ak napr. ActiveDocument je null? Bude RX rukoväť to správne? Očakávam, že v tomto prípade podmienka, aby sa jeho predvolená hodnota (alebo aspoň false štandardne)
Spook

Ak ActiveDocumentdostanete NullReferenceException. Toto nemá nič do činenia s RX.
mm8

V mojej knižnici nebudem. To je, okrem iného, je, prečo som záujem, či RX je dobre-vhodný pre túto úlohu.
Spook

V iných jazykoch

Táto stránka je v iných jazykoch

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................