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

时间:2009-05-14 11:31:46

标签: wpf xaml data-binding expression-blend datacontext

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

  • 代码,如下所示:

App.xaml.cs(取自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:

<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中做很多事情,例如从您的数据源等中选择字段as shown here

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

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

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

7 个答案:

答案 0 :(得分:15)

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

首先确保在根元素中定义了以下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将无法实例化您的课程

答案 1 :(得分:5)

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

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

答案 2 :(得分:1)

在代码隐藏中使用它可以很容易地使用unity注入datacontext。

答案 3 :(得分:1)

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

它将说明DataContext的类型,这对于Blend来说应该足以获取属性。

我还没有尝试过这个,所以请耐心等待,但这当然值得研究。

答案 4 :(得分:1)

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

答案 5 :(得分: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

答案 6 :(得分:0)

根据我的经验,最好至少针对它将呈现的数据样本设计界面布局。否则就是对廉价的见解和昂贵的疏忽视而不见。