在代码中设置 DataContext 而不是 XAML 有什么好处? [英] What is the advantage of setting DataContext in code instead of XAML?

查看:25
本文介绍了在代码中设置 DataContext 而不是 XAML 有什么好处?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 WPF 中定义 DataContext 似乎有两种主要方式:

There seem to be two main ways to define DataContext in WPF:

  • 或者在代码中像这样:

App.xaml.cs(取自 WPF MVVM 工具包模板):

App.xaml.cs (taken from the WPF MVVM Toolkit template):

public partial class App : Application
{
    private void OnStartup(object sender, StartupEventArgs e)
    {
        // Create the ViewModel and expose it using the View's DataContext
        MainView mainView = new MainView();
        MainViewModel mainViewModel = new MainViewModel();
        mainViewModel.LoadCustomers("c:\testdata2\Customers.xml");
        mainView.DataContext = mainViewModel;
        mainView.Show();
    }
}

  • 在 XAML 中 像这样:
  • Window1.xaml:

    Window1.xaml:

    <DockPanel>
        <StackPanel
            HorizontalAlignment="Left"
            DockPanel.Dock="Top"
            Orientation="Horizontal">
            <StackPanel.DataContext>
                <local:CustomerViewModel />
            </StackPanel.DataContext>
            <TextBlock Text="{Binding Path=FirstName}" />
            <TextBlock Text=" " />
            <TextBlock Text="{Binding Path=LastName}" />
        </StackPanel>
    
        <StackPanel
            HorizontalAlignment="Left"
            VerticalAlignment="top"
            DockPanel.Dock="Top"
            Orientation="Horizontal">
            <ListBox ItemsSource="{Binding Source={StaticResource FileNames}}" />
        </StackPanel>
    
        <StackPanel
            HorizontalAlignment="Left"
            VerticalAlignment="top"
            DockPanel.Dock="Top"
            Orientation="Horizontal">
            <ComboBox
                ItemsSource="{Binding Source={StaticResource Directories}}"
                SelectedIndex="0" />
        </StackPanel>
    
        <StackPanel
            HorizontalAlignment="Left"
            VerticalAlignment="top"
            DockPanel.Dock="Top"
            Orientation="Horizontal">
            <StackPanel.DataContext>
                <local:SystemInformationViewModel />
            </StackPanel.DataContext>
            <TextBlock Text="{Binding Path=CurrentTime}" />
        </StackPanel>
    </DockPanel>
    

    在 XAML 中定义 DataContext 的一个优点是您的数据显示在 Expression Blend 设计模式中,并且 Expression Blend 允许您在 GUI 中做很多事情,例如从您的数据源等中选择字段.如此处所示.

    One advantage that defining the DataContext in XAML has is that your data shows up in Expression Blend design mode and Expression Blend allows you to do quite a lot within the GUI e.g. choose fields from your datasource, etc. as shown here.

    我读到绑定 ADO.NET 对象不能在 XAML 中绑定(虽然我不明白为什么你可以为它们编写一个可以从 XAML 绑定到的最小包装器).

    I have read that binding ADO.NET objects cannot be bound in XAML (although I don't see why you could write a minimal wrapper for them to which you could bind from XAML).

    奇怪的是,WPF 团队在制作 WPF MVVM 模板时在代码中定义了 DataContext,这很快使得在 Expression Blend 中编辑视图变得不切实际,因为您的数据没有出现在设计中模式通常是布局的重要组成部分.

    Strange that the WPF Team in making the WPF MVVM templates define the DataContext in code which very quickly makes it impracticable to edit your Views in Expression Blend, since your data doesn't show up in design mode which is often a significant part of the layout.

    所以我认为在使用代码而不是 XAML 设置 DataContext 的道路上一定有一些优势,有人知道它是什么吗?

    So I'm thinking there must be some advantage down the road to setting the DataContext in code instead of XAML, anyone know what it is?

    推荐答案

    您可以(也许在 2009 年不能)通过使用 d:DataContext 属性来两全其美.你不需要任何 ViewModelLocator 疯狂 如果你还没有准备好:-)

    You can (maybe in 2009 you couldn't) get the best of both worlds by using the d:DataContext attribute. You don't need any of that ViewModelLocator craziness if you're not ready for that yet :-)

    首先确保您在根元素中定义了以下 XML 命名空间:

    First make sure that you have the following XML namespace defined in your root element:

    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    

    然后您可以将以下属性添加到您的 xaml 中的元素:

    Then you can add the following attribute to an element in your xaml:

    d:DataContext="{d:DesignInstance IsDesignTimeCreatable=True, Type=vm:CustomerInsightViewModel}"

    在您的 xaml 代码隐藏中:

    In your xaml codebehind :

        public CustomerInsightUserControl()
        {
            InitializeComponent();
    
            if (!DesignerProperties.IsInDesignTool)
            {
                DataContext = new CustomerInsightViewModel();
            }
        }
    

    然后在您的 ViewModel 中:

    Then in your ViewModel:

        public CustomerInsightViewModel()
        {
            if (IsInDesignMode)
            {
                // Create design time data
                Customer = new Customer() {
                    FirstName=... 
                }
            }
            else {
                // Create datacontext and load customers
            }
        }
    

    不要错过 IsDesignTimeCreatable=True 否则 Blend 不会实例化您的类

    Don't miss the IsDesignTimeCreatable=True or else Blend won't instantiate your class

    这篇关于在代码中设置 DataContext 而不是 XAML 有什么好处?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆