14

在 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();
    }
}
  • 或者像这样在 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 中做很多事情,例如从数据源中选择字段等,如此处所示

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

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

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

4

7 回答 7

16

d:DataContext通过使用该属性,您可以(也许在 2009 年您不能)获得两全其美的效果。如果你还没有准备好,你就不需要任何那种ViewModelLocator疯狂:-)

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

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

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

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

在您的 xaml 代码隐藏中:

    public CustomerInsightUserControl()
    {
        InitializeComponent();

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

然后在您的 ViewModel 中:

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

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

于 2010-08-01T05:32:33.110 回答
6

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

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

于 2009-05-14T11:38:36.537 回答
1

将它放在代码隐藏中可以很容易地使用统一注入数据上下文。

于 2009-05-14T11:33:34.427 回答
1

可能有一种解决方案,使用 DataObjectProvider 来掩盖数据在 XAML 之外实例化的事实。

它将说明 DataContext 的类型是什么,这应该足以让 Blend 获取属性。

我还没有尝试过,所以请谨慎对待,但这当然值得研究。

于 2009-05-14T12:00:57.763 回答
1

请参阅 Rob 关于 Blend 中设计时数据的文章:http ://www.robfe.com/2009/08/design-time-data-in-expression-blend-3/

于 2009-12-04T15:25:04.660 回答
1

还应该可以使用 ObjectDataProvider 使用 Unity 或此处暗示的其他 IOC 建立对象工厂...

http://social.msdn.microsoft.com/Forums/en/wpf/thread/1ff9e90e-302e-436e-bab3-ca4bad2b85af

尤其是...

http://www.codeproject.com/Articles/43806/WPF-Ninject-Dojo-The-Data-Provider.aspx

于 2011-03-31T00:43:10.300 回答
0

In my experience, it is best to design an interface layout against at least a sample of the data it will present. To do otherwise is to be blind to cheap insights and expensive oversights.

于 2011-03-21T17:18:06.637 回答