微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在WPF/Silverlight/XAML中强类型数据绑定?

我最大的宠物之一是如何使用XAML数据绑定是没有选择强烈键入你的数据绑定。换句话说,在C#中,如果你想访问一个不存在的对象的属性,你不会从Intellisense获得任何帮助,如果你坚持忽略Intellisense,编译器会抓住你,让你继续 – 我怀疑这里的很多人都会同意这是一个很好的事情。但是在XAML数据绑定中,你没有网络。你可以绑定任何东西,即使它不存在。事实上,考虑到XAML数据绑定的奇怪语法,并且根据我自己的经验,绑定到存在的东西要比绑定到不存在的东西要复杂得多。我更可能得到我的数据绑定语法错误,得到它的权利;和比较时间我花在疑难解答XAML数据绑定容易使我花在微软的堆栈的任何其他部分(包括尴尬和讨厌的WCF,如果你可以相信)的时间。大多数(不是所有的)回到这样的事实,没有强类型的数据绑定,我不能从Intellisense或编译器得到任何帮助。

所以我想知道的是:为什么MS不至少给我们一个选项强烈类型的数据绑定:有点像在VB6中,我们可以使任何对象变体,如果我们是真正的虐待,但大多数时间,使用正常的类型化变量是有意义的。有什么原因MS不能这样做吗?

这里是我的意思的例子。在C#中,如果属性“UsrID”不存在,您将收到Intellisense的警告和编译器的错误,如果你尝试这样:

string userID = myUser.UsrID;

但是,在XAML中,您可以根据需要执行此操作:

<TextBlock Text="{Binding UsrID}" />

既不是Intellisense,编译器,或(最惊人的)应用程序本身在运行时会给你任何提示,你做错了。现在,这是一个简单的例子,但是任何处理复杂对象图和复杂UI的现实应用程序都会有大量的等效方案,这些方案并不简单,也不容易排除故障。即使你第一次正确地工作,你是SOL如果你重构你的代码和更改你的C#属性名称。一切都将编译,它会运行没有错误,但没有什么可以工作,让你去寻找和啄你的方式通过整个应用程序,试图找出什么破碎。

一个可能的建议(在我的头顶部,我没有想过)可能会是这样的:

对于逻辑树的任何部分,您可以在XAML中指定其期望的对象的DataType,如下所示:

<Grid x:Name="personGrid" BindingDataType="{x:Type collections:ObservableCollection x:TypeArgument={data:Person}}">

这可能产生强类型的ObservableCollection< Person> TypedDataContext属性在.g.cs文件中。所以在你的代码中:

// This would work
personGrid.TypedDataContext = new ObservableCollection<Person>(); 

// This would trigger a design-time and compile-time error
personGrid.TypedDataContext = new ObservableCollection<Order>();

如果你通过网格上的控件访问TypedDataContext,它会知道你试图访问的对象是什么类型。

<!-- It kNows that individual items resolve to a data:Person -->
<ListBox ItemsSource="{TypedBinding}">
    <ListBox.ItemTemplate>
       <DataTemplate>
           <!--This would work -->
           <TextBlock Text="{TypedBinding Path=Address.City}" />
           <!-- This would trigger a design-time warning and compile-time error,since it has the path wrong -->
           <TextBlock Text="{TypedBinding Path=Person.Address.City} />
       </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

我做了一个博客发布here,更多地解释了我对WPF / XAML数据绑定的沮丧,我认为这将是一个明显更好的方法。有什么理由为什么这不能工作吗?是否有人知道MS是否计划解决这个问题(按照我的建议,或希望,一个更好的一个)?

解决方法

Ken,C#将从一个简洁的语法元素中获益,用于引用一个PropertyInfo类。 PropertyInfo结构是在编译时定义的静态对象,因此为对象上的每个Property提供唯一的键。然后可以在编译时验证属性

唯一的问题是将对象的实例作为数据类型的奇怪,因为强类型在类型上强制执行,而不是类型的值。传统上,编译器不强制执行数据值,而是依赖运行时代码来检查其数据。大多数情况下,它甚至不可能在编译时验证数据,但反射是其中至少可能的边缘情况之一。

或者,编译器可以为每个属性创建一个新的数据类型。我可以想象很多类型被创建,但这将使编译时强制的属性绑定。

一种想法是,CLR引入了一个反射水平,与之前的系统相比,它是另一个数量级的反射。它现在被用来做一些相当令人印象深刻的东西,如数据绑定。但是它的实现仍然在元数据级别,从编译器为每种数据类型生成一种报告。我想一种方式来增长C#将是提升元数据编译时间检查。

在我看来,有人可能开发一个编译工具,增加了反射级验证。新的智慧是这样的。一般来说,发现要与PropertyInfos进行比较的字符串参数是非常棘手的,但这不是不可能的。可以定义一种新的数据类型,如“PropertyString”,它清楚地标识将来与PropertyInfos进行比较的参数。

无论如何,我感到你的痛苦。我已经下了很多拼写错误属性名称引用。老实说,WPF中有很多与反射有关的刺激。一个有用的实用程序将是一个WPF强制检查器,确保所有的静态控制构造函数都在适当位置,属性正确定义,绑定是准确的,正确的密钥等。有一个长的可以执行的验证列表。

如果我还在为微软工作,我可能会尝试这样做。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐