WPF MVVM 직선 XAML 창보기가 아닌 ContentControl + DataTemplate보기를 사용하는 이유는 무엇입니까?
저를 괴롭히는 WPF의 MVVM에 대한 질문이 있습니다.
다음과 같은 이유 :?
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>
ExampleView.xaml을 다음과 같이 설정하십시오.
<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>
그리고 다음과 같이 창을 만듭니다.
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();
}
}
다음과 같이 할 수있는 경우 :?
App.xaml : (시작 창 /보기 설정)
<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 : (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>
기본적으로 "View as DataTemplate"(VaD) 대 "View as Window"(VaW)
비교에 대한 나의 이해는 다음과 같습니다. (참고로 VS 2008을 사용하므로 Blendability 및 / 또는 기타 항목이 부족합니다)
- VaD : 창을 닫지 않고 뷰를 전환 할 수 있습니다. (이것은 내 프로젝트에 바람직하지 않습니다)
- VaD : VM은 View에 대해 전혀 알지 못하지만 VaW에서는 다른 창을 열 때만 인스턴스화 할 수 있어야합니다.
- VaW: I can actually see my xaml rendered in the Designer (I can't with VaD, at least in my current setup)
- VaW: Works intuitively with opening and closing windows; each window has (is) a corresponding View (and ViewModel)
- VaD: ViewModel can pass along initial window width, height, resizability etc. through properties (whereas in VaW they are directly set in the Window)
- VaW: Can set FocusManager.FocusedElement (not sure how in VaD)
- VaW: Less files, since my window types (e.g. Ribbon, Dialog) are incorporated into their Views
So what's going on here? Can't I just build my windows in XAML, access their data cleanly through properties of the VM, and be done with it? The code-behind is the same (virtually nil). I'm struggling to understand why I should shuffle all the View stuff into a ResourceDictionary. ( But I don't want to do it wrong ;-) )
Does it even matter? Is there something I've missed? Thanks a lot for reading. :O
Thanks to Rachel Lim and Nick Polyak for my blossoming understanding of MVVM
Edit: Minor flow change
People use DataTemplates
that way when they want to dynamically switch Views depending on the 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>
So,
if Window.DataContext
is an instance of VM1
, then View1
will be displayed,
and if
Window.DataContext
is an instance of VM2
, then View2
will be displayed.
Granted, it makes no sense at all if only 1 View is expected, and never changed.
I hope this is clear enough :P
Since in VaD the view models know nothing about the views, you can build a fully functioning application entirely made up of view models only and no views. This leads to the possibility of writing an application that can be driven entirely by code. This in turn leads to the possibility of performing integration testing without the GUI. Integration testing through the GUI is notoriously fragile - while testing through view models should be more robust.
From my personal experience: Both work models are aviables, depending of what you want, and depending of the application requirements. The idea behind VaD
is decopling the content, and the container. If you implement VaD
you can use this template (by default) when ever you show any item of this type. You can use it in ItemsControls
(lists, listviews, grids, etc) and in ContentControls
only making bindings. Like you said, VaD
works for switching the window's content with out closing and opening a new. Also you can define the view using UserControls
, then you take control if focused elements, and also you can manage code behind. So, your data template may be like this:
<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>
You also in an UserControl
may set dependency properties, thats make easier the job, because allow bindings and decoupling the app.
But of course, if you app doesn't require dynamically content switching, it is fine to use VaW
for the main window, or any other window. In fact, you can use both VaW
and VaD
. This last one can be used for inner items in the app, that doesn't require windows. You shoose what is better for you, depending of application requirements, and the time aviable for developing the app. Hope this personal experience helps...
'Program Tip' 카테고리의 다른 글
구문 분석 중 Python 예기치 않은 EOF (0) | 2020.10.21 |
---|---|
Dart는 열거를 지원합니까? (0) | 2020.10.21 |
app.yaml을 사용하여 GAE에 환경 변수를 안전하게 저장 (0) | 2020.10.21 |
PyCharm 내에서 (Ana) conda 사용 (0) | 2020.10.21 |
RuntimeError : 모듈이 API 버전 A에 대해 컴파일되었지만이 버전의 numpy는 9입니다. (0) | 2020.10.21 |