如何使用DataContext属性在XAML中的窗口上设置ViewModel?

Nic*_*las 90 .net wpf xaml mvvm

这个问题几乎说明了一切.

我有一个窗口,并尝试使用完整的命名空间将DataContext设置为ViewModel,但我似乎做错了.

<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">
Run Code Online (Sandbox Code Playgroud)

Jos*_*osh 138

试试这个.

<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>
Run Code Online (Sandbox Code Playgroud)

  • 有没有办法使用`Window`元素上的属性设置数据上下文,如`DataContext ="VM:MainWindowViewModel"? (12认同)
  • 我最喜欢这个选项.如果VM仅用于MainWindow,则似乎更清晰. (3认同)
  • @Oliver 你将不得不实现`MarkupExtension`,从来没有在虚拟机上做过,但你可以用转换器来实现,以确保只有一个转换器实例存在,并使用 `="{converters:SomethingConverter}"` 从 xaml 直接调用它,暗示 `xmlns:converters` 指向转换器命名空间。`公共抽象类 BaseValueConverter&lt;T&gt; : MarkupExtension, IValueConverter where T : class, new() { private static T _converter; 公共覆盖对象 ProvideValue(IServiceProvider serviceProvider) { return _converter ?? (_converter = new T()); } }` (2认同)

Mer*_*ham 106

除了其他人提供的解决方案(这是好的,正确的)之外,还有一种方法可以在XAML中指定ViewModel,但仍然将特定的ViewModel与View分开.当您想要编写独立的测试用例时,分离它们非常有用.

在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>
Run Code Online (Sandbox Code Playgroud)

在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}"
    />
Run Code Online (Sandbox Code Playgroud)

  • 请注意,此方法对MainWindow的每个实例使用相同的ViewModel实例.如果窗口是单实例,那么这很好,因为这种情况意味着,但是如果您正在显示窗口的多个实例,例如在MDI或选项卡式应用程序的情况下,则不行. (8认同)

Job*_*Joy 11

您需要实例化MainViewModel并将其设置为datacontext.在您的语句中,它只是将其视为字符串值.

     <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>
Run Code Online (Sandbox Code Playgroud)


Mik*_*kis 8

还有一种更好的方法来指定视图模型:

    using Wpf = System.Windows;

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

上述机制仅适用于主视图模型。为了解决下面询问用户控件的评论,该机制针对子视图模型进行了如下转换:

    public class ParentViewModel
    {
        public MyChildViewModel ChildViewModel { get; }
    
        public ParentViewModel()
        {
            ChildViewModel = new MyChildViewModel( ... );
        }
    }
Run Code Online (Sandbox Code Playgroud)

父视图.xaml:

    [...]
        xmlns:local="clr-namespace:the-namespace-of-my-wpf-stuff"
    [...]
        <local:MyChildView DataContext="{Binding ChildViewModel}" />
    [...]
Run Code Online (Sandbox Code Playgroud)

<Rant>之前提出的所有解决方案都要求视图模型具有无参数构造函数。微软的印象是系统可以使用无参数构造函数来构建。如果您也有这种印象,请务必继续使用其他一些解决方案。对于那些了解构造函数必须有参数,因此对象的实例化不能交给魔术框架的人来说,指定视图模型的正确方法就是我上面展示的方法。</Rant>