Architettura / design MVVM multi-schermo - I miei ViewModels "a schermo" contengono i sub-ViewModels?

3

Ora sto andando oltre un semplice programma MVVM, e vorrei solo controllare la mia architettura corrente e assicurarmi che stia andando giù per il percorso giusto qui.

Tutto è strutturato attorno a schermi, e questi schermi hanno una sorta di scomposizione "ad albero". Al livello superiore c'è una schermata principale e puoi eseguire il drill down attraverso le schermate correlate.

Ho fatto un esempio semplificato, un'applicazione che tiene traccia dei dipendenti per le aziende. Ha tre "schermi".

  • CompanyOverviewScreen, ti consente di vedere tutte le società che hai. Clicca per andare al seguente:
  • EmployeeTrackerScreen, ti consente di vedere tutti i dipendenti di questa azienda e la loro posizione. Clicca per andare al seguente:
  • EmployeeScreen, vediamo le informazioni su un impiegato.

Quindi gli schermi si aprono come un albero:

Domanda1:dovedovrebberoesserecreatiearchiviatiquestimodellidivisualizzazionedelloschermo?Dovrebberoesserecreatiearchiviatiinunpostosopratutto,oilEmployeeTrackerScreenViewModelpuòcreareEmployeeScreenViewModelearchiviarlocomeunaproprietàdiraccolta?

StoancheutilizzandoViewModelscondivisichenonhannovisteperidatieleproprietàdell'interfacciautenteinquesteschermateincuistannovisualizzandounaraccoltadielementi.Adesempio,EmployeeTrackerScreenViewhaunItemsCollectionpercollegarsidirettamenteaunaObservableCollectionchesonoarchiviaticomeproprietàinEmployeeTrackerScreenViewModel.

Eccounbreveschizzodicomeèstrutturato:

QuindiEmployeeTrackerScreenViewhailseguenteaspetto:

<UserControlx:Class="Project.EmployeeTrackerScreenView >
    <DockPanel>
        <StackPanel DockPanel.Dock="Top">
            <Label Content="{Binding CorporationViweModel.Name}" />
            <Label Content=" has " />
            <Label Content="{Binding CorporationViweModel.NumberOfEmployees}" />
        </StackPanel>
        <ScrollViewer>
            <ItemsControl ItemsSource="{Binding ObsvCollectionOfEmployeeViewModels}" >
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal">
                            <Label Content="{Binding EmployeeModel.Name}"/>
                            <Label Content="is"/>
                            <Label Content="{Binding EmployeeModel.Location}"/>
                        </StackPanel>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
        </ScrollViewer>
    </DockPanel>
</UserControl>

Domanda 2 è in linea con i pattern MVVM? Sto andando nel modo giusto?

Mi piacerebbe qualche commento su come sto strutturando le cose, forse qualche consiglio sul fatto che ne parlerò in modo ragionevole. Spero che la domanda fornisca informazioni sufficienti ed è appropriata. Sono nuovo di questo tipo di progettazione software, ho sempre creato app più piccole in passato, quindi sono inesperto nell'architettura appropriata.

Utilizzo il framework Caliburn Micro MVVM, in WPF se è utile saperlo.

    
posta Joe 06.02.2016 - 18:22
fonte

4 risposte

2

Normalmente ho un ApplicationViewModel che si occupa dell'inizializzazione di ViewModels per schermi separati, come questo , tuttavia perché della natura della tua applicazione, sembra che il tuo CompanyOverviewScreenViewModel funzioni bene per questo scopo.

In genere avrei la mia applicazione principale per inizializzare il contesto dei dati di livello superiore, e ogni ViewModel da lì è responsabile della creazione / manutenzione dei modellini di vista sotto di esso.

Ad esempio:

public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);

        var mainApp = new CompanyOverviewWindow();
        var appData = new CompanyOverviewScreenViewModel();
        mainApp.DataContext = appData;
        mainApp.Show();
    }
}

Il CompanyOverviewScreenViewModel conterrebbe una collezione di oggetti CompanyModel , e alla selezione ogni CompanyModel oggetto verrebbe visualizzato all'utente in qualche tipo di ContentControl o UserControl . Ogni CompanyModel avrebbe inoltre una collezione di oggetti EmployeeModel che potrebbero anche essere selezionati e visualizzati.

Ricorda che ViewModel è in realtà solo un modello della vista. Ad esempio, sembra che tu voglia solo visualizzare gli oggetti Employee, quindi usare EmployeeModel direttamente è perfettamente accettabile. Ma se volessi fornire la possibilità di aggiornare EmployeeModel e includere elementi come Salva, Annulla, Elimina, ecc. Probabilmente vorrai un ViewModel per contenere il codice extra che non è correlato all'oggetto Dati dipendente stesso.

In questo stesso senso, perché vuoi fare cose come tracciare il Dipendente selezionato di ogni CompanyModel , qualcosa che normalmente non fa parte dell'oggetto dei dati aziendali, potrebbe avere senso usare un oggetto CompanyViewModel anche a quel livello . A volte per qualcosa di semplice come il solo tracciamento della selezione, aggiungo semplicemente il modello dell'oggetto. Dipende davvero da quanto è grande o come è strutturata l'applicazione.

Nel complesso ciò che hai ora sembra che stai andando nella giusta direzione, anche se ho avuto qualche preoccupazione per la tua immagine in cui si dice "Ogni schermata crea ViewModels .." in alto a sinistra angolo. In genere non sostengo un approccio view-first per MVVM e WPF e raccomanderei invece un approccio ViewModel-first, come descritto qui.

    
risposta data 11.03.2016 - 20:06
fonte
1

Riguardo alla prima domanda:

Suggerirei di incapsulare il processo di creazione del modello di visualizzazione dallo schermo. Puoi introdurre la classe che utilizzerà i modelli per creare un modello di visualizzazione correlato.

class EmployeeTrackerScreenViewModelCollector {
  func addEmployeeModels(models: [EmployeeTrackerScreenModel])
  func collectViewModels() -> [EmployeeTrackerScreenViewModel]
}

Questa classe può raccogliere / ordinare / filtrare e fornire array pronti per la visualizzazione con i modelli di visualizzazione.

Informazioni su dove memorizzare viewModels, non vedo alcun problema per memorizzare ciò che mostri sullo schermo. Oppure se hai una classe dataSource separata per il tuo schermo, puoi archiviare l'array viewModels lì.     
risposta data 09.02.2016 - 22:54
fonte
1

Posso solo condividere alcune considerazioni sulla progettazione concettuale del tuo problema. Lascerò il codice da usare perché non ho familiarità con i framework.

Per prima cosa una nota importante; il ViewModel, come altri hanno detto, è il modello di una vista. Questo, di conseguenza, significa che puoi avere un viewmodel per vista. Ora, non confondere le visualizzazioni con schermate o moduli. In una schermata o in un modulo o in una finestra, è possibile avere più visualizzazioni. Ad esempio, diciamo che in uno degli schermi dei tuoi dipendenti hai una specie di dashboard con un grafico sulle tasse o l'assicurazione che pagano e un elenco con i benefici che ricevono. Il grafico e l'elenco sono due "viste" differenti, il che significa che sono necessari due viewmodels per preparare i dataset per le due viste.

Where should these screen view models be created and stored? Should they be created and stored in one place above everything, or should the EmployeeTrackerScreen ViewModel create the EmployeeScreen ViewModel and store it as a collection property?

Per capire come funziona, è necessario considerare chi è responsabile di mostrare la finestra / finestra di dialogo dello schermo del tracker. C'è una specie di dibattito nella comunità MVVM riguardo alla domanda che stai ponendo. Prenderò un approccio pragmatico qui. Se View e ViewModel hanno vita breve (come nella schermata EmployeeScreen nelle figure) puoi creare ViewModel nello stesso posto in cui crei e mostrare la finestra attuale (la vista). Se stai parlando di un viewmodel a livello di applicazione (qualcosa di cui hai sempre bisogno), allora puoi fare quello che dice Rachel. Di nuovo, puoi ottenere approcci diversi in questo.

Un altro approccio per i modelli e i modelli di visualizzazione a livello di applicazione sarebbe avere una fabbrica che generi le istanze delle classi e un localizzatore di servizi prima ancora che tu mostri la finestra principale della tua app. C'è anche polemica sul fatto che il localizzatore di servizi debba essere favorito o meno. Su questo, ti suggerisco di fare la tua lettura e vedere quali argomenti ti stanno bene.

    
risposta data 10.05.2017 - 02:58
fonte
-4

Non ho familiarità con il framework Caliburn Micro MVVM, Se sei aperto a un altro framework, ti consiglierò di usare PRISM da microsoft ( link ). Con PRISM puoi facilmente visualizzare e gestire le tue visualizzazioni (schermo).

    
risposta data 11.03.2016 - 18:52
fonte

Leggi altre domande sui tag