WPF MVVM De ce să folosiți Vizualizări ContentControl + DataTemplate mai degrabă decât Vizualizări de ferestre XAML simple? (Programare, C#, Wpf, Xaml, Mvvm, Arhitectură)

Simon F a intrebat.

De ce acest lucru?

MainWindow.xaml:

<Window x_Class="MVVMProject.MainWindow"
    
    xmlns_x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Grid>
        <ContentControl Content="{Binding}"/>
    </Grid>
</Window>

Aveți ExampleView.xaml configurat ca:

<ResourceDictionary 
    xmlns_x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns_vms="clr-namespace:MVVMProject.ViewModels">
    <DataTemplate DataType="{x:Type vms:ExampleVM}" >
        <Grid>
            <ActualContent/>
        </Grid>
    </DataTemplate>
</ResourceDictionary>

Și creați fereastra astfel:

public partial class App : Application {

    protected override void OnStartup(StartupEventArgs e) {

        base.OnStartup(e);

        MainWindow app = new MainWindow();
        ExampleVM context = new ExampleVM();
        app.DataContext = context;
        app.Show();
    }
}

Când se poate face așa?

App.xaml: (Setați fereastra de pornire/View de pornire)

<Application x_Class="MVVMProject.App"
    
    xmlns_x="http://schemas.microsoft.com/winfx/2006/xaml"
    StartupUri="ExampleView.xaml">
</Application>

ExampleView.xaml: (o fereastră, nu un ResourceDictionary)

<Window x_Class="MVVMProject.ExampleView"
    
    xmlns_x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns_vms="clr-namespace:MVVMProject.ViewModels">
    >
    <Window.DataContext>
        <vms:ExampleVM />
    </Window.DataContext>

    <Grid>
        <ActualContent/>
    </Grid>
</Window>

În esență, este „View as DataTemplate” (VaD) vs. „View as Window” (VaW)

Iată cum înțeleg eu comparația:

  • VaD: vă permite să schimbați vizualizările fără a închide fereastra. (Acest lucru nu este de dorit pentru proiectul meu)
  • VaD: VM nu știe absolut nimic despre View, în timp ce în cazul VaW trebuie (doar) să fie capabil să o instanțieze la deschiderea unei alte ferestre.
  • VaW: pot vedea efectiv xaml-ul meu redat în Designer (nu pot cu VaD, cel puțin în configurația mea actuală).
  • VaW: funcționează intuitiv cu deschiderea și închiderea ferestrelor; fiecare fereastră are (este) un View (și ViewModel) corespunzător.
  • VaD: ViewModel poate transmite lățimea inițială a ferestrei, înălțimea, capacitatea de redimensionare etc. prin intermediul proprietăților (în timp ce în VaW acestea sunt setate direct în fereastră).
  • VaW: poate seta FocusManager.FocusedElement (nu sunt sigur cum se face în VaD).
  • VaW: mai puține fișiere, deoarece tipurile mele de ferestre (de exemplu, Ribbon, Dialog) sunt încorporate în vizualizările lor.

Deci, ce se întâmplă aici? Nu pot să-mi construiesc ferestrele în XAML, să le accesez datele în mod curat prin intermediul proprietăților VM și să termin cu ele? Code-behind-ul este același (practic nul).

Mă străduiesc să înțeleg de ce ar trebui să amestec toate chestiunile legate de View într-un ResourceDictionary.

Comentarii

  • Gândiți-vă astfel: ViewModels se afișează fie în Windows, fie în UserControls. Poco’s vor fi afișate în DataTemplates. 🙂 –  > Por dev hedgehog.
3 răspunsuri
Federico Berasategui

Oamenii folosesc DataTemplates acest mod atunci când vor să schimbe dinamic vizualizările în funcție de ViewModel:

<Window>
    <Window.Resources>
       <DataTemplate DataType="{x:Type local:VM1}">
          <!-- View 1 Here -->
       </DataTemplate>

       <DataTemplate DataType="{x:Type local:VM2}">
          <!-- View 2 here -->
       </DataTemplate>
    </Window.Resources>

    <ContentPresenter Content="{Binding}"/>

</Window>

Deci,

dacă Window.DataContext este o instanță de VM1, , atunci View1 va fi afișat,

iar dacă

Window.DataContext este un exemplu de VM2, , atunci View2 va fi afișat.

De acord, nu are niciun sens dacă se așteaptă doar 1 Vizualizare și nu se modifică niciodată.

Phillip Ngan

Deoarece în VaD modelele de vizualizare nu știu nimic despre vizualizări, puteți construi o aplicație complet funcțională, alcătuită numai din modele de vizualizare și nu din vizualizări. Acest lucru duce la posibilitatea de a scrie o aplicație care poate fi condusă în întregime de cod. Acest lucru duce, la rândul său, la posibilitatea de a efectua teste de integrare fără GUI. Testarea integrării prin intermediul interfeței grafice este cunoscută ca fiind fragilă – în timp ce testarea prin intermediul modelelor de vizualizare ar trebui să fie mai robustă.

Raúl Otaño

Din experiența mea personală: Ambele modele de lucru sunt aviabile, în funcție de ceea ce doriți și în funcție de cerințele aplicației. Ideea din spatele VaD este decodificarea conținutului și a containerului. Dacă implementați VaD puteți utiliza acest model (în mod implicit) atunci când afișați orice element de acest tip. Îl puteți utiliza în ItemsControls (liste, liste, grile etc.) și în ContentControls numai realizarea de legături. Așa cum ați spus, VaD funcționează pentru a schimba conținutul ferestrei fără a închide și a deschide una nouă. De asemenea, puteți defini vizualizarea folosind UserControls, , apoi preluați controlul asupra elementelor focalizate și, de asemenea, puteți gestiona codul din spate. Așadar, șablonul de date poate fi următorul:

<ResourceDictionary 
xmlns_x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns_vms="clr-namespace:MVVMProject.ViewModels">
<DataTemplate DataType="{x:Type vms:ExampleVM}" >
    <CustomUserControl A="{Binding A}" B="{Binding B}" DataContext="{Binding}" .../>
</DataTemplate>

De asemenea, în cadrul unui UserControl puteți seta proprietăți de dependență, ceea ce vă ușurează munca, deoarece permite legături și decuplarea aplicației.

Dar, bineînțeles, dacă aplicația dvs. nu necesită schimbarea dinamică a conținutului, puteți utiliza VaW pentru fereastra principală sau pentru orice altă fereastră. De fapt, puteți utiliza atât VaW și VaD. Acesta din urmă poate fi utilizat pentru elementele interne ale aplicației, care nu necesită ferestre. Alegeți ce este mai bine pentru dumneavoastră, în funcție de cerințele aplicației și de timpul disponibil pentru dezvoltarea aplicației.Sper ca această experiență personală să vă ajute…