在代码中设置DataContext而不是XAML有什么好处?

Edw*_*uay 13 data-binding wpf datacontext xaml expression-blend

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

  • 无论是在代码是这样的:

App.xaml.cs(取自WPF MVVM Toolkit模板):

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();
    }
}
Run Code Online (Sandbox Code Playgroud)
  • 或者像这样的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>
Run Code Online (Sandbox Code Playgroud)

在XAML中定义DataContext的一个优点是,您的数据显示在Expression Blend设计模式中,Expression Blend允许您在GUI中执行相当多操作,例如从数据源中选择字段等,如此处所示.

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

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

所以我认为在代码中设置DataContext而不是XAML 必须有一些优势,任何人都知道它是什么?

Sim*_*ver 15

你可以(可能在2009年你不能)通过使用d:DataContext属性获得两全其美.如果你尚未做好准备,你不需要任何这种ViewModelLocator疯狂 :-)

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

xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
Run Code Online (Sandbox Code Playgroud)

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

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

在你的xaml代码隐藏中:

    public CustomerInsightUserControl()
    {
        InitializeComponent();

        if (!DesignerProperties.IsInDesignTool)
        {
            DataContext = new CustomerInsightViewModel();
        }
    }
Run Code Online (Sandbox Code Playgroud)

然后在你的ViewModel中:

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

不要错过,IsDesignTimeCreatable=True否则Blend不会实例化你的课程

  • 如果您收到编译时错误,则"属性'DataContext'必须位于默认命名空间中...",此解决方案位于http://stackoverflow.com/q/8303803/62278 (2认同)

Hak*_*onB 5

我不喜欢让Expression Blend尝试实例化我的数据对象.

我通过代码设置DataContext,我可以使用依赖注入来注入适当的对象,服务,提供程序或我用来查找代码的其他内容.


Ali*_*fai 1

将其放在代码隐藏中可以轻松使用 Unity 注入数据上下文。