要么 ”你如何确保所有绑定保持正确?“
(这有点冗长,但请耐心等待,我尽量做到尽可能短)
请考虑以下示例:
<TextBox Name="tb" />
<TextBlock Text="{Binding Text.TheProp, ElementName=tb}" />
在编译时完全知道绑定是不正确的(即解析器知道元素的类型 tb
,因此,它知道它的类型 Text
财产,因此,它知道 TheProp
不存在)。
但是,此代码将编译并运行(尽管在调试输出中有绑定错误消息)。
在某些情况下,这种行为可能非常方便:无论我的数据类型是什么,只要它具有适当命名的属性,我就可以了。因此,我们得到了一种“声明性的鸭子打字”。
然而鸭打字并不总是好事。
具体来说,在使用MVVM模式时,我(大部分时间)都知道我所有ViewModel对象的确切类型。另一方面,模型随着时间的推移变得越来越复杂,这使我对未来的重构感到担忧:如果我决定重命名一些属性,或者,上帝禁止,将它们放在一个单独的聚合对象中会怎么样?然后我的所有绑定会发生什么?我是否必须手动耙所有XAML文件?即使没有重构 - 如果我只是打错了怎么办?
在XAML的其他地方已经解决了类似的问题。例如,如果您输入了错误的属性名称 Style/Setter/@Property
,你得到一个编译时错误。
TemplateBinding
还提供此类验证。哪个非常方便。
所以,理想情况下,我希望看到这样的事情:
ProductViewModel.cs:
public class ProductViewModel
{
public Name { get; set; }
public Price { get; set; }
}
ProductView.XAML:
<UserControl x:Class="Shopping.View.ProductView"
x:DataContextType="vm:ProductViewModel"
xmlns:vm="clr-namespace:Shopping.ViewModel"
... >
<TextBox Text="{Binding Name}" /> <!-- OK -->
<TextBox Text="{Binding Price}" /> <!-- OK -->
<TextBox Text="{Binding ABC}" /> <!-- Compile time error: there is no property ABC in ProductViewModel -->
</UserControl>
ShoppingCart.XAML:
<UserControl x:Class="Shopping.View.ShoppingCartView"
x:DataContextType="vm:ShoppingCartViewModel"
xmlns:vm="clr-namespace:Shopping.ViewModel"
... >
<ItemsControl ItemsSource="{Binding Products}"
ItemType="vm:ProductViewModel" > <!-- Static check happens here
ShoppingCartViewModel.Products must
implement IEnumerable<ProductViewModel> -->
<ItemsControl.ItemTemplate>
<DataTemplate DataType="vm:ProductViewModel">
<view:ProductView /> <!-- DataContext is known to be of correct type
because of DataTemplate.DataType property -->
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</UserControl>
但让我们回到现实。实际上,所有梦想都不会在不久的将来发生。
但是,我确信我不是第一个遇到这个问题的人。
所以,最后,问题是: 你如何确保你的绑定是正确的?并且他们保持这种方式?