WPF MVVM Tại sao sử dụng Chế độ xem ContentControl + DataTemplate thay vì Chế độ xem cửa sổ XAML thẳng?


83

Tại sao là cái này?

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>

Thiết lập exampleView.xaml của bạn thành:

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

Và tạo cửa sổ như sau:

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();
    }
}

Khi nào nó có thể được thực hiện như thế này?

App.xaml: (Đặt cửa sổ khởi động / Chế độ xem)

<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: (một Cửa sổ không phải là một 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>

Về cơ bản, đó là "View as DataTemplate" (VaD) so với "View as Window" (VaW)

Đây là hiểu biết của tôi về sự so sánh:

  • VaD: Cho phép bạn chuyển đổi Chế độ xem mà không cần đóng cửa sổ. (Điều này không mong muốn cho dự án của tôi)
  • VaD: VM hoàn toàn không biết gì về View, trong khi trong VaW, nó (chỉ) có thể khởi tạo nó khi mở một cửa sổ khác
  • VaW: Tôi thực sự có thể thấy xaml của mình được hiển thị trong Trình thiết kế (tôi không thể với VaD, ít nhất là trong thiết lập hiện tại của tôi)
  • VaW: Hoạt động trực quan với việc mở và đóng cửa sổ; mỗi cửa sổ có (là) một View tương ứng (và ViewModel)
  • VaD: ViewModel có thể truyền theo chiều rộng, chiều cao, khả năng thay đổi kích thước của cửa sổ ban đầu, v.v. thông qua các thuộc tính (trong khi trong VaW, chúng được đặt trực tiếp trong Window)
  • VaW: Có thể đặt FocusManager.FocusedElement (không chắc về cách thức trong VaD)
  • VaW: Ít tệp hơn, vì các loại cửa sổ của tôi (ví dụ: Ribbon, Hộp thoại) được tích hợp vào Chế độ xem của chúng

Vậy điều gì đang xảy ra ở đây? Tôi không thể chỉ xây dựng các cửa sổ của mình trong XAML, truy cập dữ liệu của chúng một cách sạch sẽ thông qua các thuộc tính của máy ảo và được thực hiện với nó? Mã phía sau là như nhau (hầu như không).

Tôi đang đấu tranh để hiểu tại sao tôi nên xáo trộn tất cả các nội dung Chế độ xem vào một ResourceDictionary.


2
Hãy nghĩ như thế này: ViewModels sẽ được hiển thị trong Windows hoặc UserControls. Poco's sẽ được hiển thị trong DataTemplates. :)
dev nhím

Câu trả lời:


130

Mọi người sử dụng DataTemplatestheo cách đó khi họ muốn tự động chuyển Chế độ xem tùy thuộc vào Mô hình xem:

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

Vì thế,

if Window.DataContextlà một phiên bản của VM1, then View1sẽ được hiển thị,

và nếu

Window.DataContextlà một thể hiện của VM2, sau đó View2sẽ được hiển thị.

Đúng là không có ý nghĩa gì nếu chỉ có 1 Lượt xem được mong đợi và không bao giờ thay đổi.


8

Vì trong VaD, các mô hình chế độ xem không biết gì về các chế độ xem, bạn có thể xây dựng một ứng dụng hoạt động đầy đủ hoàn toàn chỉ bao gồm các mô hình chế độ xem và không có chế độ xem nào. Điều này dẫn đến khả năng viết một ứng dụng có thể được điều khiển hoàn toàn bằng mã. Điều này dẫn đến khả năng thực hiện kiểm tra tích hợp mà không có GUI. Kiểm tra tích hợp thông qua GUI nổi tiếng là mỏng manh - trong khi kiểm tra thông qua các mô hình xem sẽ mạnh mẽ hơn.


5

Từ kinh nghiệm cá nhân của tôi: Cả hai mô hình làm việc đều có thể sử dụng được, tùy thuộc vào những gì bạn muốn và tùy thuộc vào các yêu cầu ứng dụng. Ý tưởng đằng sau VaDlà giải mã nội dung và vùng chứa. Nếu bạn triển khai, VaDbạn có thể sử dụng mẫu này (theo mặc định) khi bạn hiển thị bất kỳ mục nào thuộc loại này. Bạn có thể sử dụng nó trong ItemsControls(danh sách, dạng xem danh sách, lưới, v.v.) và ContentControlschỉ trong việc tạo ràng buộc. Giống như bạn đã nói, VaDhoạt động để chuyển đổi nội dung của cửa sổ mà không đóng và mở một cửa sổ mới. Ngoài ra, bạn có thể xác định chế độ xem bằng cách sử dụng UserControls, sau đó bạn kiểm soát nếu các phần tử được tập trung và bạn cũng có thể quản lý mã phía sau. Vì vậy, mẫu dữ liệu của bạn có thể như sau:

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

Bạn cũng UserControlcó thể đặt các thuộc tính phụ thuộc, điều này giúp công việc dễ dàng hơn, vì cho phép các ràng buộc và tách ứng dụng.

Nhưng tất nhiên, nếu ứng dụng của bạn không yêu cầu chuyển đổi nội dung động, bạn có thể sử dụng VaWcho cửa sổ chính hoặc bất kỳ cửa sổ nào khác. Trên thực tế, bạn có thể sử dụng cả hai VaWVaD. Cái cuối cùng này có thể được sử dụng cho các mục bên trong ứng dụng, không yêu cầu cửa sổ. Bạn chọn những gì tốt hơn cho mình, tùy thuộc vào yêu cầu của ứng dụng và thời gian thích hợp để phát triển ứng dụng. Hy vọng kinh nghiệm cá nhân này sẽ giúp ...

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.