您可以以强类型的方式编写每个单独的绑定:
<TextBox Text="{Binding Path=(vm:Site.Contact).(vm:Contact.Name)}" />
然而,这并不能验证TextBox DataContext的类型是ViewModel.Site(我认为这是不可能的,但我可能错了)。
FrameworkElement.DataContext
是一种依赖属性,它使数据绑定成为可能,其类型为object
。
正如其他人所指出的那样,您可以为称为DataTemplate
的特殊模板指定DataContext
的预期类型。许多控件(例如ItemsControl
、ControlControl
)提供了访问DataTemplates的功能,以允许您设置可视化表示对DataContext类型的期望。
Bryan是正确的,他没有测试他的代码。
应用正确的类型化DataTemplate的方法如下:
<Window>
<Window.Resources>
<DataTemplate x:Key="TypedTemplate" DataType="{x:Type myViewModel}">
...
</DataTemplate>
</Window.Resources>
<ContentControl Content="{Binding}" ContentTemplate="{StaticResource TypedTemplate}" />
</Window>
ContentPresenter 直接继承自 FrameworkElement,并且没有 Template 属性。此外,Template 属性通常是指 ControlTemplate 类型的 Control.Template,它与 DataTemplate 完全不同。
我认为 Bryan 想到的是 ContentControl
,它是两种根控件类型之一(另一个是 ItemsControl
)。ContentControl
确实继承自 Control。因此,如果我们选择,我们可以在其上指定 Template 属性。
<Window>
<Window.Resources>
<DataTemplate x:Key="TypedTemplate" DataType="{x:Type myViewModel}">
...
</DataTemplate>
<ControlTemplate x:Key="ControlSkin" TargetType="{x:Type ContentControl}">
...
</ControlTemplate>
</Window.Resources>
<ContentControl Content="{Binding}" ContentTemplate="{StaticResource TypedTemplate}" Template="{StaticResource ControlSkin}" />
</Window>
不,目前的规范在Xaml中没有强类型。我相信随着.Net 4.0的出现,Xaml应该会具备泛型的能力。有了这个,我认为在Xaml中实现强类型会更加容易。
我个人为我的ViewModel中的每个属性声明一个静态PropertyPath,并使用x:static作为绑定路径进行引用 - 例如:
public class MyViewModel
{
public static PropertyPath MyPropertyPath = new PropertyPath("MyProperty");
public bool MyProperty{get; set;}
}
{Binding Path={x:Static local:MyViewModel.MyPropertyPath}}
,请注意保留HTML标签。试试这个:
<Window>
<Window.Resources>
<DataTemplate x:Key="TypedTemplate" DataType="{x:Type myViewModel}">
...
</DataTemplate>
</Window.Resources>
<ContentPresenter Content="{Binding}" Template="{StaticResource TypedTemplate}" />
</Window>
我还没有测试过这段代码,但它应该能给你一个想法。内容呈现器将显示当前的DataContext,它将使用DataTemplate。虽然编译器中它不是强类型的,但会在加载时立即抛出运行时错误(在窗口的InitializeComponent中)。如果出现问题,你应该能够在测试中轻松捕获到这个错误。