绑定的静态验证

时间:2010-09-04 14:57:36

标签: wpf binding

或“如何确保所有绑定都保持正确?
(这有点长,但请耐心等待,我尽量做到尽可能短)

考虑以下示例:

    <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>

但让我们回到现实。实际上,所有梦想都不会在不久的将来发生。

但是,我确信我不是第一个遇到这个问题的人 所以,最后,问题是:如何确保绑定是正确的?并且他们保持这种状态?

2 个答案:

答案 0 :(得分:8)

您的Xaml的静态分析如何作为构建后步骤执行?

作为.Net 4的一部分,Microsoft发布了一个新的System.Xaml库,以提供独立于WPF的强大的Xaml解析和序列化支持。他们现在开始在它上面构建各种有趣的东西,其中一些可能会帮助你。

例如,在XamlToolkit中,您会找到XamlDOM,它可以让您轻松地对Xaml文件进行静态分析。进一步说,有FxCop rules for XAML

最感兴趣的是Rob Relyea的BindingFinder,其明确的目标是在Xaml中检查Bindings的类型。这要求您在Xaml中具有类型提示,例如DataTemplate中的DataType属性,或者视图中的新d:DataContext attribute(Blend用于提供设计时数据)。然后它使用XamlDOM检查所有内容是否匹配。

更新: Resharper 6现在提供intellisense for data bindings,并在您的财产路径出错时发出警告。

答案 1 :(得分:2)

实际上,我从未发现这是一个问题,至少在使用MVVM模式时。视图模型仅存在于视图的支持中。我不打算改变一个而不改变另一个。重构视图模型不会破坏视图中的绑定,因为重构视图模型本身是没有意义的。您只会在(并且因为)更改视图设计时重构视图模型。

我没有这个问题的另一个原因是我没有独立于Expression Blend开发视图模型。对于除了最简单的UI之外的所有UI,我使用某种依赖注入构建我的视图模型,以便我可以创建可在Expression Blend中使用的测试数据源。当我在Blend中创建绑定时,我立刻知道我是否做得对。

与一般的MVVM一样,在你了解自己在做什么以及为什么这样做之前,这样做是一个难以置信的痛苦。 (This long blog postJonasFollesø对如何使用Ninject进行了很好的概述,尽管你可以使用其他框架的结尾。)我确信我有问题还没有发现这种方法 - 除了我已经将DI框架和Expression Blend添加到我需要理解的开发WPF应用程序的堆上的问题之外。

Pablo Casals说,不断的实验让艺术家保持年轻。我感觉年轻。