[c#] WPF MVVM 직선 XAML 창보기 대신 ContentControl + DataTemplate보기를 사용하는 이유는 무엇입니까?

왜 이래?

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)입니다.

비교에 대한 나의 이해는 다음과 같습니다.

  • VaD : 창을 닫지 않고 뷰를 전환 할 수 있습니다. (이것은 내 프로젝트에 바람직하지 않습니다)
  • VaD : VM은 뷰에 대해 전혀 알지 못하지만 VaW에서는 다른 창을 열 때만 인스턴스화 할 수 있어야합니다.
  • VaW : 실제로 디자이너에서 xaml이 렌더링되는 것을 볼 수 있습니다 (적어도 현재 설정에서는 VaD를 사용할 수 없습니다).
  • VaW : 창을 열고 닫을 때 직관적으로 작동합니다. 각 창에는 해당 View (및 ViewModel)가 있습니다.
  • VaD : ViewModel은 속성을 통해 초기 창 너비, 높이, 크기 조정 가능성 등을 전달할 수 있습니다 (VaW에서는 창에서 직접 설정 됨).
  • VaW : FocusManager.FocusedElement를 설정할 수 있습니다 (VaD에서 방법이 확실하지 않음).
  • VaW : 내 창 유형 (예 : 리본, 대화 상자)이 뷰에 통합되므로 파일이 적습니다.

그래서 여기서 무슨 일이 일어나고 있습니까? XAML로 창을 빌드하고 VM의 속성을 통해 데이터에 깔끔하게 액세스 한 다음 작업을 수행 할 수는 없나요? 코드 숨김은 동일합니다 (거의 없음).

모든 View 항목을 ResourceDictionary로 섞어 야하는 이유를 이해하는 데 어려움을 겪고 있습니다.



답변

사람들 DataTemplates은 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>

그래서,

경우는 Window.DataContext의 인스턴스 VM1, 다음 View1, 표시됩니다

그리고 만약

Window.DataContext의 인스턴스 인 VM2다음, View2표시됩니다.

물론,보기가 1 개만 예상되고 변경되지 않으면 전혀 의미가 없습니다.


답변

VaD에서 뷰 모델은 뷰에 대해 아무것도 모르기 때문에 뷰 모델 만 있고 뷰가없는 완전히 작동하는 애플리케이션을 구축 할 수 있습니다. 이로 인해 전적으로 코드로 구동 할 수있는 애플리케이션을 작성할 수 있습니다. 이는 GUI없이 통합 테스트를 수행 할 수있는 가능성으로 이어집니다. GUI를 통한 통합 테스트는 취약한 것으로 악명이 높지만 뷰 모델을 통한 테스트는 더 강력해야합니다.


답변

내 개인적인 경험으로 볼 때 : 두 작업 모델은 사용자가 원하는 것과 응용 프로그램 요구 사항에 따라 사용할 수 있습니다. 뒤에있는 아이디어 VaD는 콘텐츠와 컨테이너를 디 카플링하는 것입니다. 구현 VaD하는 경우이 유형의 항목을 표시 할 때마다 기본적으로이 템플릿을 사용할 수 있습니다. ItemsControls(목록, 목록보기, 그리드 등) 및 ContentControls바인딩을 만드는 데만 사용할 수 있습니다 . 당신이 말했듯이, VaD새 창을 닫고 열지 않고 창 내용을 전환하는 작업입니다. 또한를 사용하여 뷰를 정의한 UserControls다음 포커스가있는 요소를 제어 할 수 있으며 코드 뒤에서 코드를 관리 할 수도 있습니다. 따라서 데이터 템플릿은 다음과 같을 수 있습니다.

<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>

또한 UserControl바인딩을 허용하고 앱을 분리하기 때문에 종속성 속성을 설정할 수도 있습니다.

물론 앱에 동적 콘텐츠 전환이 필요하지 않은 경우 VaW기본 창이나 다른 창에 사용하는 것이 좋습니다. 실제로 VaWVaD. 이 마지막 항목은 창을 필요로하지 않는 앱의 내부 항목에 사용할 수 있습니다. 애플리케이션 요구 사항과 앱 개발에 소요되는 시간에 따라 더 나은 것을 선택합니다. 이 개인적인 경험이 도움이되기를 바랍니다.


답변