Dlaczego to?
MainWindow.xaml:
<Window x:Class="MVVMProject.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<ContentControl Content="{Binding}"/>
</Grid>
</Window>
Ustaw plik ExampleView.xaml jako:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
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 utwórz okno w ten sposób:
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();
}
}
Kiedy można to zrobić w ten sposób?
App.xaml: (Ustaw okno startowe / Widok)
<Application x:Class="MVVMProject.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="ExampleView.xaml">
</Application>
ExampleView.xaml: (okno, a nie ResourceDictionary)
<Window x:Class="MVVMProject.ExampleView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
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>
Zasadniczo jest to „Wyświetl jako szablon danych” (VaD) a „Wyświetl jako okno” (VaW)
Oto moje rozumienie porównania:
- VaD: Umożliwia przełączanie widoków bez zamykania okna. (Nie jest to pożądane w moim projekcie)
- VaD: VM nie wie absolutnie nic o widoku, podczas gdy w VaW musi (tylko) mieć możliwość jego instancji podczas otwierania innego okna
- VaW: Faktycznie widzę mój Xaml renderowany w Projektancie (nie mogę z VaD, przynajmniej w mojej obecnej konfiguracji)
- VaW: działa intuicyjnie przy otwieraniu i zamykaniu okien; każde okno ma (jest) odpowiadający mu Widok (i ViewModel)
- VaD: ViewModel może przechodzić wzdłuż początkowej szerokości okna, wysokości, możliwości zmiany rozmiaru itp. Poprzez właściwości (podczas gdy w VaW są one ustawiane bezpośrednio w oknie)
- VaW: można ustawić FocusManager.FocusedElement (nie wiem jak w VaD)
- VaW: Mniej plików, ponieważ moje typy okien (np. Wstążka, Okno dialogowe) są włączone do ich widoków
Więc co się tutaj dzieje? Czy nie mogę po prostu zbudować moich okien w XAML, uzyskać czysty dostęp do ich danych poprzez właściwości maszyny wirtualnej i skończyć z tym? Kod jest taki sam (praktycznie zerowy).
Usiłuję zrozumieć, dlaczego powinienem przetasować wszystkie elementy widoku do ResourceDictionary.
Odpowiedzi:
Ludzie używają
DataTemplates
tego sposobu, gdy chcą dynamicznie przełączać widoki w zależności od 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>
Więc,
jeśli
Window.DataContext
jest instancjąVM1
, toView1
zostanie wyświetlone,i jeśli
Window.DataContext
jest instancjąVM2
, a następnieView2
zostanie wyświetlony.To prawda, nie ma to żadnego sensu, jeśli oczekiwany jest tylko 1 widok i nigdy się nie zmienia.
źródło
Ponieważ w VaD modele widoków nie wiedzą nic o widokach, można zbudować w pełni funkcjonalną aplikację składającą się wyłącznie z modeli widoków bez widoków. Prowadzi to do możliwości napisania aplikacji, która może być sterowana w całości przez kod. To z kolei prowadzi do możliwości wykonania testów integracyjnych bez GUI. Testowanie integracji przez GUI jest notorycznie delikatne - podczas gdy testowanie za pomocą modeli widoku powinno być bardziej niezawodne.
źródło
Z mojego osobistego doświadczenia: oba modele pracy są dostępne, w zależności od tego, czego chcesz i w zależności od wymagań aplikacji. Ideą
VaD
jest usunięcie zawartości i pojemnika. Jeśli zaimplementujeszVaD
, możesz użyć tego szablonu (domyślnie), gdy pokażesz jakikolwiek element tego typu. Możesz go używać wItemsControls
(listach, widokach list, siatkach itp.) IContentControls
tylko podczas tworzenia powiązań. Jak powiedziałeś,VaD
działa w celu przełączania zawartości okna bez zamykania i otwierania nowego. Możesz również zdefiniować widok za pomocąUserControls
, a następnie przejąć kontrolę nad elementami, które są skupione, a także możesz zarządzać kodem za. Twój szablon danych może więc wyglądać następująco:<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 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>
Możesz również
UserControl
ustawić właściwości zależności, które ułatwiają zadanie, ponieważ zezwalają na powiązania i oddzielenie aplikacji.Ale oczywiście, jeśli Twoja aplikacja nie wymaga dynamicznego przełączania treści, można jej użyć
VaW
w oknie głównym lub dowolnym innym oknie. W rzeczywistości możesz używać obuVaW
iVaD
. Ten ostatni może być używany do elementów wewnętrznych w aplikacji, które nie wymagają okien. Wybierasz, co jest dla Ciebie lepsze, w zależności od wymagań aplikacji i czasu dostępnego na jej opracowanie. Mam nadzieję, że to osobiste doświadczenie pomoże ...źródło