Wpf 在代码中设置DataContext而不是XAML的优点是什么?
在WPF中定义DataContext似乎有两种主要方法:Wpf 在代码中设置DataContext而不是XAML的优点是什么?,wpf,xaml,data-binding,expression-blend,datacontext,Wpf,Xaml,Data Binding,Expression Blend,Datacontext,在WPF中定义DataContext似乎有两种主要方法: 代码中的如下所示: App.xaml.cs(摘自): 或在XAML中如下所示: Window1.xaml: <DockPanel> <StackPanel HorizontalAlignment="Left" DockPanel.Dock="Top" Orientation="Horizontal"> <StackPanel.Da
- 代码中的如下所示:
- 或在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 MVVM模板的WPF团队在代码中定义了DataContext,这很快使在Expression Blend中编辑视图变得不切实际,因为您的数据不会显示在设计模式中,而设计模式通常是布局的重要部分
所以我认为在代码中设置DataContext而不是XAML的过程中肯定有一些优势,有人知道它是什么吗?在codebehind中设置DataContext可以很容易地使用unity注入DataContext。我不喜欢让Expression Blend尝试实例化我的数据对象
我通过代码设置DataContext,在这里我可以使用依赖项注入来注入适当的对象、服务、提供者或我用来查找代码的其他内容 可能有一种解决方案,使用DataObjectProvider来掩盖数据在XAML之外实例化的事实 它将说明DataContext的类型,这应该足以让Blend拾取属性
我还没有尝试过这一点,所以请恕我直言,但它确实值得研究。请参阅Rob关于Blend中设计时数据的文章:通过使用
d:DataContext
属性,您可以(也许在2009年您无法)充分利用这两个方面的优势。如果您还没有准备好,您不需要任何这些:-)
首先确保在根元素中定义了以下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
}
}
不要错过
isdesigntimecreateable=True
,否则Blend不会实例化您的类根据我的经验,最好至少根据它将显示的数据样本设计一个接口布局。否则,就是对廉价的洞察和昂贵的疏忽视而不见。也可以使用ObjectDataProvider使用Unity或此处暗示的其他IOC建立对象工厂
特别是
是否有一个两全其美的解决方案?这是否意味着,如果您使用复合应用程序库/Unity,您基本上可以从Expression Blend中剪切和粘贴,或者是否有一种简单的方法,例如在XAML中使用模拟默认数据上下文,设计者可以在Blend中使用?请参阅我在DataobjectProvider上的回答。它可以用作一个门面来委托实例化并使用来自DI的内容。如果在开始“属性'DataContext'必须在默认命名空间中…”时出现编译时错误,解决方案如下
public CustomerInsightViewModel()
{
if (IsInDesignMode)
{
// Create design time data
Customer = new Customer() {
FirstName=...
}
}
else {
// Create datacontext and load customers
}
}