Esiste un buon modello formale per gestire lo stato in MVVM?

17

Ho iniziato a conoscere Redux e React nel mondo del web, e più ne imparo più mi sto rendendo conto di quanto sia dolorosa la gestione dello stato nel mondo desktop con l'architettura in stile MVVM di WPF (usando Caliburn specificamente associare le viste a ViewModels).

Redux ha alcuni semplici principi che stabiliscono come deve essere gestito lo stato, rendendo più prevedibili gli aggiornamenti dell'interfaccia utente, la gestione degli eventi e le modifiche dello stato. I principi sono:

  • Una singola fonte di verità (tutti gli stati mutabili sono memorizzati in un singolo oggetto condiviso).
  • Lo stato è di sola lettura. Non può essere modificato dai componenti attraverso il codice, che è in genere ciò che accade in WPF.
  • Lo stato può essere modificato solo da pure funzioni.

L'architettura MVVM di WPF consente di creare viste interattive molto rapidamente, ma il debug dei problemi quando vari viewmodels ed eventi cambiano stato è un incubo. Ad esempio: un evento licenziato che ha modificato una vista e ha provato a impostare una scheda predefinita, ma i dati non hanno completato il caricamento in modo asincrono da un servizio Web, quindi la scheda non esiste (ancora) quindi non accade nulla

Ho impiegato ore a disegnare diagrammi per cercare di comprendere interazioni complesse tra componenti viewModels correlati tra loro che si aggiornano l'un l'altro.

Comprendo che Redux mira a risolvere parte di questo stato di imprevedibilità. C'è qualcosa di simile, o un modello architettonico che si adatterebbe bene con WPF per aiutare a gestire meglio lo stato? Non sono sicuro di quanto bene funzionino i principi di Redux in .NET perché non li ho ancora provati. Forse qualcuno ha qualche esperienza che può dare qualche consiglio?

    
posta willem 27.04.2016 - 16:27
fonte

1 risposta

6

Penso di sapere cosa intendi. Fondamentalmente si risolve il problema aggiungendo un 'controller' o un 'viewmodel' master '(scusa psudocode)

es

public class MasterVM
{
    public ChildVM View1 {get;set;}
    public ChildVM View2 {get;set;}

    private Data data;
    public MasterVM()
    {
        View1.OnEvent += updateData;
    }

    private Action<int> updateData(int value)
    {
         View2.Value = value;
    }
}

quando lo fai con il pattern del mediatore, penso alla classe come a un controller. vale a dire.

public class Controller
{
    public Controller(MediatorService m)
    {
        m.Subscribe("valueupdated", updateData);
    }

    private Action<int> updateData(int value)
    {
         m.Publish("showvalue", value);
    }
}

public class View2
{
    public View2(MediatorService m)
    {
        m.Subscribe("showvalue", (int v)=> {Value = v;});
    }
}

Questo tipo di cose ti consente di inserire la tua 'logica di flusso' o l'orchestrazione di eventi in queste classi persistenti ad alto livello e di mantenere il codice delle macchine virtuali leggero. Se si desidera modificare "quando l'utente fa clic su ACQUISTA, l'ordine viene elaborato", il tipo di cose che si possono vedere in "OrderFlowController" o "OrderProcessVM" o comunque si desidera nominarli. Piuttosto che una combinazione di BasketVM, PaymentVM, 3dSecureVM ecc. Ecc.

Quindi nel tuo specifico esempio della "scheda non ancora pronta" potresti avere

public class Controller
{
    bool dataLoadCompleted;
    public Controller(MediatorService m)
    {
        m.Subscribe("setTabRequest", setTab); //message from view model with set tab button
        m.Subscribe("dataLoadComplete", dataLoadComplete); //message from data loading view model or some other controller?
    }

    private Action<int> setTab(int value)
    {
         if(!dataLoadCompleted)
         {
             m.Publish("error", "Please wait for data to load"); //message for error alert view model
         }
         else
         {
             m.Publish("setDefaultTab", value); //message for tab viewmodel
         }
    }

    private Action dataLoadComplete()
    {
         //persist state;
         dataLoadCompleted = true;
    }
}
    
risposta data 27.04.2016 - 21:05
fonte

Leggi altre domande sui tag