Làm cách nào để đặt ViewModel trên một cửa sổ trong XAML bằng thuộc tính DataContext?


96

Câu hỏi nói lên tất cả.

Tôi có một cửa sổ và đã cố gắng đặt DataContext bằng cách sử dụng không gian tên đầy đủ thành ViewModel, nhưng dường như tôi đã làm sai điều gì đó.

<Window x:Class="BuildAssistantUI.BuildAssistantWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    DataContext="BuildAssistantUI.ViewModels.MainViewModel">

Câu trả lời:


112

Ngoài giải pháp mà người khác đã cung cấp (tốt và chính xác), có một cách để chỉ định ViewModel trong XAML, nhưng vẫn tách ViewModel cụ thể khỏi View. Tách chúng rất hữu ích khi bạn muốn viết các trường hợp thử nghiệm riêng biệt.

Trong App.xaml:

<Application
    x:Class="BuildAssistantUI.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:BuildAssistantUI.ViewModels"
    StartupUri="MainWindow.xaml"
    >
    <Application.Resources>
        <local:MainViewModel x:Key="MainViewModel" />
    </Application.Resources>
</Application>

Trong MainWindow.xaml:

<Window x:Class="BuildAssistantUI.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    DataContext="{StaticResource MainViewModel}"
    />

Oh wow ... cảm ơn. Tôi đã đánh dấu điều này là đã trả lời, nhưng phần bổ sung của bạn được đánh giá cao. Sẽ sử dụng nó.
Nicholas

@Nicholas: Câu trả lời khác là hoàn hảo cho câu hỏi, vì vậy tôi đồng ý với quyết định của bạn
Merlyn Morgan-Graham

8
Chỉ cần lưu ý rằng phương pháp này sử dụng cùng một phiên bản ViewModel cho mọi phiên bản MainWindow. Điều đó tốt nếu cửa sổ là một bản sao như trường hợp này ngụ ý, nhưng không tốt nếu bạn đang hiển thị nhiều bản sao của cửa sổ, chẳng hạn như trong trường hợp MDI hoặc ứng dụng theo thẻ.
Josh

1
Trên thực tế, câu trả lời của Josh tốt hơn vì nó cung cấp cho bạn sự an toàn về kiểu chữ trên DataContext. Vì vậy, bạn có thể liên kết trực tiếp với DataContext mà không cần lo lắng về việc nhập tên / đường dẫn thuộc tính nào đó.
Josh M.

149

Hãy thử điều này thay thế.

<Window x:Class="BuildAssistantUI.BuildAssistantWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:VM="clr-namespace:BuildAssistantUI.ViewModels">
    <Window.DataContext>
        <VM:MainViewModel />
    </Window.DataContext>
</Window>

3
Tôi thích lựa chọn này nhất. Có vẻ sạch hơn nếu VM chỉ được sử dụng cho MainWindow.
Andrew Grothe

13
Có cách nào để đặt bối cảnh dữ liệu bằng cách sử dụng một thuộc tính trên Windowphần tử, như thế DataContext="VM:MainWindowViewModel"nào không?
Oliver

Đây là cách thích hợp!
JavierIEH

Tôi không hoàn toàn hiểu tại sao một cách lại tốt hơn cách kia. Ngoài ra, tôi không hoàn toàn thấy sự khác biệt về một trong hai cách này so với cách tôi đã thấy một số người sử dụng "Tài nguyên động". Cái này là cái gì?
Travis Tubbs

1
@Oliver bạn sẽ phải triển khai MarkupExtension, chưa bao giờ thực hiện trên máy ảo, nhưng bạn có thể làm điều đó với các bộ chuyển đổi để đảm bảo chỉ có một phiên bản của bộ chuyển đổi và gọi nó một cách trực tiếp từ xaml với ="{converters:SomethingConverter}", ngụ ý xmlns:converterscác điểm tại không gian tên của bộ chuyển đổi. public abstract class BaseValueConverter<T> : MarkupExtension, IValueConverter where T : class, new() { private static T _converter; public override object ProvideValue(IServiceProvider serviceProvider) { return _converter ?? (_converter = new T()); } }
Whazz

11

Bạn cần khởi tạo MainViewModel và đặt nó làm datacontext. Trong câu lệnh của bạn, nó chỉ coi nó là giá trị chuỗi.

     <Window x:Class="BuildAssistantUI.BuildAssistantWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:BuildAssistantUI.ViewModels">
      <Window.DataContext>
        <local:MainViewModel/>
      </Window.DataContext>

Cảm ơn, tôi đã tìm thấy nó đang làm điều đó.
Nicholas

3

Bạn có thể muốn thử Catel . Nó cho phép bạn xác định một lớp DataWindow (thay vì Window) và lớp đó tự động tạo mô hình khung nhìn cho bạn. Bằng cách này, bạn có thể sử dụng khai báo ViewModel như bạn đã làm trong bài đăng gốc của mình và mô hình chế độ xem sẽ vẫn được tạo và đặt làm DataContext.

Xem bài viết này để biết ví dụ.


1

Cũng có cách này để chỉ định mô hình xem:

using Wpf = System.Windows;

public partial class App : Wpf.Application //your skeleton app already has this.
{
    protected override void OnStartup( Wpf.StartupEventArgs e ) //you need to add this.
    {
        base.OnStartup( e );
        MainWindow = new MainView();
        MainWindow.DataContext = new MainViewModel( e.Args );
        MainWindow.Show();
    }
}

<Rant>

Tất cả các giải pháp được đề xuất trước đây đều yêu cầu MainViewModelphải có một hàm tạo không tham số.

Microsoft có ấn tượng rằng hệ thống có thể được xây dựng bằng cách sử dụng các hàm tạo không tham số. Nếu bạn cũng có ấn tượng đó, hãy tiếp tục và sử dụng một số giải pháp khác.

Đối với những người biết rằng các hàm tạo phải có các tham số, và do đó việc khởi tạo các đối tượng không thể nằm trong tay của các khung phép thuật, cách thích hợp để chỉ định mô hình khung nhìn mà tôi đã trình bày ở trên.

</Rant>

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.