WPF DataTemplate绑定的简单学习

转载 2013年12月03日 13:53:11
对于普通的实体类的绑定,如果只是简单的添加删除的话不需要用到INotifyPropertyChanged接口,这样的话比较简单,只需要在datatemplate中绑定后台的属性即可。然后直接往里面加入数据就可以了。

  如果用到了INotifyPropertyChanged这个接口的话这个可以实现在后台增加删改数据的时候前台能够同步显示。同时,前台修改数据,也能同步反应到绑定源中。使用这个接口时需要使用ObservableCollection集合类,这个类就是实现了INotifyCollectionChanged接口的一个集合类。还要设置IsSynchronizedWithCurrentItem="True",如果集合类中的实体属性在后台发生变化,则在UI中动态显示变化。

  附加两个差不多的demo

源码下载

  本文来自世界很灰暗的博客,原文地址:http://www.cnblogs.com/socialdk/archive/2012/08/30/2664649.html

 

WPF中DataTemplate基本原理与缺陷分析

 

这个文章来源于这样一个问题。下面的两种做 法,在效果上有什么不同?(注:Header是一个自定义DP。)

 

 
<TabItem Header="{Binding Header, ElementName=window}">
<TextBox Text="{Binding Header, ElementName=window}" 
Name="headerName"/>
</TabItem>

 

 

 
<DataTemplate x:Key="TabTemplate">
<TextBox Text="{Binding Header, ElementName=window}" 
Name="headerNameInTemplate"/>
</DataTemplate>
<TabItem Header="{Binding Header, ElementName=window}" 
ContentTemplate="{StaticResource TabTemplate}"/>

 

一种是直接在TabItem里放一个TextBox,另一种是通过DataTemplate间接地放进去。这两种方式,从外观上看,没有区别。拿到XamlPad里看VisualTree,控件的结构上也没有区别。

图1. 直接使用TextBox

图2. Template中的TextBox

在开发WPF程序的时候,常常会使用到DataTemplate,以通过MVVM模式实现从数据生成UI。我们当然也会希望用与不用DataTemplate的行为最好也是一样的。而且目前来看,这两种界面看上去一样,VisualTree也是一样的。行为应该也会一样的。

但是愿望是美好的,实现却是残酷的。两种不同的实现方式,虽然看上去一样,但是行为却是不同的。这里有一个示例程序,看看大家能不能找到两种实现方式有什么不同呢?

图3. 示例运行图

如果你还没有猜到原因,或是懒得研究示例代码,就继续看下面的分析吧。

上面的分析,一直都是建立在空间相似性的比较上。两种实现方式,从空间结构的角度上来说的确是一样。我们再来考虑一下过程。

先来了解一下TabControl和示例的情况,算是先给大家一些提示。

1. 当直接在TabItem里放TextBox时,TabItem的Content就是一个实实在在的控件。

2. 当使用DataTemplate时,这上面的示例代码中,TabItem的Content是空的。

3. TabControl虽然有多个TabItem,但是当前显示的TabItem只有一个。而且更重要的是,无论TabItem如何切换,TabControl一直是用同一个ContentPresenter把当前TabItem里的Content显示出来的。参考图一、二中的蓝色部分,那个控件,就是TabControl的主体部分,在切换Tab时是不会变的。

当在TabControl里切换不同的TabItem时,如果发现Content是一个控件,比如示例中的TextBox,那就把这个TextBox显示出来。如果发现Content是个Object,而同时使用了DataTemplate。就会应用这个DataTemplate。

 

问题就在于,DataTemplate是如何被应用的?

微软关于DataTemplate的官方文档只介绍了如何使用DataTemplate,却似乎并没有介绍DataTemplate的工作原理(也许有,不过一直没有找到)。

文档上是如此解释DataTemplate的。

“The WPF data templating model provides you with great flexibility to define the presentation of your data.”

就是说,为从数据展示(或者说是生成)界面提供了极大的灵活性。

但是通读全文,微软也没有讲过,用DataTemplate和不用DataTemplate有什么不同。基本上通篇就是在介绍DataTemplate的优点。没有介绍一个缺点。但是说实在了,我们在比较不同技术的时候,通常都会去比较其优点和缺点。如果之前没有了解过一个技术的缺点就贸然使用,势必会遇到无法预期的情况,给开发的进度造成影响。

以下对于DataTemplate原理的分析,是笔者根据DataTemplate的实际效果分析出来的,没有官方的资料确认,可能有不少错误,欢迎大家指正。

从DataTemplate的目标和效果来看。DataTemplate是一种运行时行为。就是在程序加载数据之前,DataTemplate是没有起作用的。而这时其它非DataTemplate控件都已经加载了。加载数据之后,WPF会根据数据的类型或控件本身指定DataTemplate资料来进一步加载DataTemplate中的控件。

考虑下面的几种情况:

1. 两个控件,使用了相同的DataTemplate。拿前文中的例子来说,两个TabItem都用了同一个DataTemplate,DataTemplate里有一个TextBox,那么最后生成的界面中,两个TabItem里,是两个不同的TextBox还是同一个TextBox呢?

2. 还是拿上面的例子,稍微改一下,让两个TabItem用不同的DataTemplate。那么在两个TabItem之间切换的时候,看不到的那个TabItem的DataTemplate Generated 控件是不是存在的,还是已经被回收了?

大家可以先想一下再继续看。

 

对于前文的例子而言。问题1 的答案是,是同一个TextBox。那第2个问题也就不用回答了。

但是对于WPF整体而言,答案是不确定的。问题的答案取决于DataTemplate是否设置了x:Shared属性(这个属性很奇怪,在VS的Intellisence是无法自动出来的)和DataTemplate使用在什么控件上。上文的例子,没有设置这个属性,默认的值是True,而又由于TabControl只有一个ContentPresenter,所以DataTemplate里的东西会共享。呜,好复杂。

如果将x:Shared属性设置为False,那第1个问题的答案就是不同的TextBox了。对于第2 个问题,答案是会被回收掉。但是要知道,如果在TabItem里直接放TextBox,那么在切换TabItem时,每个TabItem里的TextBox是不会回收的。

 

DataTemplate的这些特性有什么问题吗?有,而且对于要求比较高的商业软件来说,还不小呢。目前发现的主要有下面两个。

1. 光标的位置丢失。

2. DataBinding不会UpdateSource。

先来解释一下第一个问题。光标的位置丢失,这个问题说大不大,说小不小。我们打开Visual Studio,再多打开几个源代码文件,然后在各个文件间切换一下,看看光标的位置会不会被保存下来呢?然而,使用了DataTemplate之后,无论x:Shared如何设置(结果会有不同),光标的位置都不会正确。我们就不得不再去维护这个光标的位置。

问题二,分类讨论一下。如果x:Shared为True,就是默认情况。两个TabItem里用的其实就是同一个TextBox,那么在切换Tab时,就不会触发TextBox的LostFocus事件,DataBinding就不会更新DataSource。如果x:Shared为False,由于切换Tab时,前一个Tab里的TextBox会被回收丢。那么DataBinding能不能UpdateSource,就变成了,TextBox被回收之前,会不会先触发一次LostFocus。经过实验,TextBox在被回收前,没有触发LostFocus事件。(在此要感谢一下我的同事Shelvin Yuan,是他发现的这个问题。才有了这篇文章。)

对于问题二的解决方案就多了,可以设置DataBinding的UpdateSourceTrigger属性,可以自定义一个TextBox,在回收时,手工触发一次LostFocus,同时设置x:Shared为False,还可以自己在切换Tab时手工地UpdateSource。

 

但是这些解决方案看上去都不太完美。DataTemplate就不能没有这些副作用吗?很遗憾,笔者还没有找到最佳的解决方案,使得使用DataTemplate和不使用DataTemplate的效果完成一样。

目前而言,DataTemplate完全是一种运行时行为。笔者能想到一个方案就是让程序员DataTemplate可以设置的行为,既可以是运行时的行为,也可以是静态的类似预编译指令的行为。比如可以通过给DataTemplate添加加一个x:IsStatic属性来设置其行为。还是拿上面的代码为例,编译器如果发然这个属性是Ture,就把DataTemplate里的东西展开,内联到TabItem中,就和直接使用TextBox一样了。

不过这只是一个美好的愿望。目前只能去找Workaround的方案了。

 

相关文章推荐

WPF模板数据绑定及事件模板绑定

变更通知是WPF的一个精髓,它使得MVVM成为WPF的标准架构!在数据绑定中,除了正常的数据模版绑定,还会涉及到模板内控件的事件绑定,以及对parent内容的绑定!接下来的示例将会展示大部分常用的绑定...

WPF 点击 datatemplate 里面的控件,获取相应绑定的数据

这个文章的标题写的十分拗口,实际上是在WPF的资源字典中创建一个数据模板,并在数据模板中添加一个Button按钮,默认情况下,在窗体中单击应用了数据模板的ListBox控件数据项中的按钮时,是不会选中...

WPF中DataTemplate基本原理与缺陷分析

WPF中DataTemplate基本原理与缺陷分析 这个文章来源于这样一个问题。下面的两种做 法,在效果上有什么不同?(注:Header是一个自定义DP。)   TabItem He...

WPF后台动态添加TabItem并设置样式

1、前台myWindow.xaml文件中的代码                      ...
  • xqf222
  • xqf222
  • 2013-06-04 23:13
  • 14689

简单的WPF TreeView绑定

  • 2014-02-13 17:20
  • 57KB
  • 下载

WP7 使用数据模板DataTemplate进行数据绑定

一、DataTemplate DataTemplate 类  描述数据对象的可视结构。 命名空间:  System.Windows  XAML     templateContent...

Windows Phone 7 使用数据模板DataTemplate进行数据绑定

转自:Windows Phone 7 使用数据模板DataTemplate进行数据绑定 一、DataTemplate DataTemplate 类  描述数据对象的可视结构。 命名空间:  ...
  • f10_s
  • f10_s
  • 2014-01-03 16:40
  • 851

WPF简单数据绑定demo

  • 2014-06-10 16:21
  • 65KB
  • 下载

WPF 简单数据绑定实例

创建一个WPF窗体,加一个TextBox和Button控件,控件button用于控制数据更改,TextBox用于显示更改后的数据,这项数据对于WinForm来说是很容易实现的,用控件点击事件对另一个控...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)