如何触发DataTemplateSelector属性当知觉条件发生变化时时

理解 JavaScript 中的 Function.prototype.bind - 文章 - 伯乐在线
& 理解 JavaScript 中的 Function.prototype.bind
函数绑定(Function binding)很有可能是你在开始使用JavaScript时最少关注的一点,但是当你意识到你需要一个解决方案来解决如何在另一个函数中保持this上下文的时候,你真正需要的其实就是 Function.prototype.bind(),只是你有可能仍然没有意识到这点。
第一次遇到这个问题的时候,你可能倾向于将this设置到一个变量上,这样你可以在改变了上下文之后继续引用到它。很多人选择使用 self, _this 或者 context 作为变量名称(也有人使用 that)。这些方式都是有用的,当然也没有什么问题。但是其实有更好、更专用的方式。
(twitter):
Jake Archibald: “我会为了作用域做任何事情,但是我不会使用 that = this”
我对这个问题更清晰的认识是在我看到之后:
Sindre Sorhus:“在jQuery中使用$this,但是对于纯JS我不会,我会使用.bind()”
而我在一开始的几个月里却忽略了这个明智的建议。
我们真正需要解决的问题是什么?
在下面的例子代码中,我们可以名正言顺地将上下文缓存到一个变量中:
var myObj = {
specialFunction: function () {
anotherSpecialFunction: function () {
getAsyncData: function (cb) {
render: function () {
var that =
this.getAsyncData(function () {
that.specialFunction();
that.anotherSpecialFunction();
myObj.render();
123456789101112131415161718192021222324
var myObj = {&&&&&specialFunction: function () {&&&&&},&&&&&anotherSpecialFunction: function () {&&&&&},&&&&&getAsyncData: function (cb) {&&&&&&&&cb();&&&&},&&&&&render: function () {&&&&&&&&var that = this;&&&&&&&&this.getAsyncData(function () {&&&&&&&&&&&&that.specialFunction();&&&&&&&&&&&&that.anotherSpecialFunction();&&&&&&&&});&&&&}};&myObj.render();
如果我们简单地使用 this.specialFunction() 来调用方法的话,会收到下面的错误:
Uncaught TypeError: Object [object global] has no method 'specialFunction'
Uncaught TypeError: Object [object global] has no method 'specialFunction'
我们需要为回调函数的执行保持对 myObj 对象上下文的引用。 调用 that.specialFunction()让我们能够维持作用域上下文并且正确执行我们的函数。 然而使用 Function.prototype.bind() 可以有更加简洁干净的方式:
render: function () {
this.getAsyncData(function () {
this.specialFunction();
this.anotherSpecialFunction();
}.bind(this));
1234567891011
render: function () {&&&&&this.getAsyncData(function () {&&&&&&&&&this.specialFunction();&&&&&&&&&this.anotherSpecialFunction();&&&&&}.bind(this));&}
我们刚才做了什么?
.bind()创建了一个函数,当这个函数在被调用的时候,它的 this 关键词会被设置成被传入的值(这里指调用bind()时传入的参数)。因此,我们传入想要的上下文,this(其实就是 myObj),到.bind()函数中。然后,当回调函数被执行的时候, this 便指向 myObj 对象。
如果有兴趣想知道 Function.prototype.bind() 内部长什么样以及是如何工作的,这里有个非常简单的例子:
Function.prototype.bind = function (scope) {
return function () {
return fn.apply(scope);
Function.prototype.bind = function (scope) {&&&&var fn = this;&&&&return function () {&&&&&&&&return fn.apply(scope);&&&&};}
还有一个非常简单的用例:
var foo = {
var bar = function(){
console.log(this.x);
bar(); // undefined
var boundFunc = bar.bind(foo);
boundFunc(); // 3
12345678910111213
var foo = {&&&&x: 3}&var bar = function(){&&&&console.log(this.x);}&bar(); // undefined&var boundFunc = bar.bind(foo);&boundFunc(); // 3
我们创建了一个新的函数,当它被执行的时候,它的 this 会被设置成 foo —— 而不是像我们调用 bar() 时的全局作用域。
浏览器支持
Version support
Firefox (Gecko)
Internet Explorer
正如你看到的,很不幸,Function.prototype.bind 在IE8及以下的版本中不被支持,所以如果你没有一个备用方案的话,可能在运行时会出现问题。
幸运的是,Mozilla Developer Network(很棒的资源库),为没有自身实现 .bind() 方法的浏览器:
if (!Function.prototype.bind) {
Function.prototype.bind = function (oThis) {
if (typeof this !== &function&) {
// closest thing possible to the ECMAScript 5 internal IsCallable function
throw new TypeError(&Function.prototype.bind - what is trying to be bound is not callable&);
var aArgs = Array.prototype.slice.call(arguments, 1),
fToBind = this,
fNOP = function () {},
fBound = function () {
return fToBind.apply(this instanceof fNOP && oThis
aArgs.concat(Array.prototype.slice.call(arguments)));
fNOP.prototype = this.
fBound.prototype = new fNOP();
1234567891011121314151617181920212223
if (!Function.prototype.bind) {&&Function.prototype.bind = function (oThis) {&&&&if (typeof this !== "function") {&&&&&&// closest thing possible to the ECMAScript 5 internal IsCallable function&&&&&&throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");&&&&}&&&&&var aArgs = Array.prototype.slice.call(arguments, 1), &&&&&&&&fToBind = this, &&&&&&&&fNOP = function () {},&&&&&&&&fBound = function () {&&&&&&&&&&return fToBind.apply(this instanceof fNOP && oThis&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& ? this&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& : oThis,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& aArgs.concat(Array.prototype.slice.call(arguments)));&&&&&&&&};&&&&&fNOP.prototype = this.prototype;&&&&fBound.prototype = new fNOP();&&&&&return fBound;&&};}
适用的模式
在学习技术点的时候,我发现有用的不仅仅在于彻底学习和理解概念,更在于看看在手头的工作中有没有适用它的地方,或者比较接近它的的东西。我希望,下面的某些例子能够适用于你的代码或者解决你正在面对的问题。
CLICK HANDLERS(点击处理函数)
一个用途是记录点击事件(或者在点击之后执行一个操作),这可能需要我们在一个对象中存入一些信息,比如:
var logger = {
updateCount: function(){
console.log(this.x);
var logger = {&&&&x: 0,&&&&&& &&&&updateCount: function(){&&&&&&&&this.x++;&&&&&&&&console.log(this.x);&&&&}}
我们可能会以下面的方式来指定点击处理函数,随后调用 logger 对象中的 updateCount() 方法。
document.querySelector('button').addEventListener('click', function(){
logger.updateCount();
document.querySelector('button').addEventListener('click', function(){&&&&logger.updateCount();});
但是我们必须要创建一个多余的匿名函数,来确保 updateCount()函数中的 this 关键字有正确的值。
我们可以使用如下更干净的方式:
document.querySelector('button').addEventListener('click', logger.updateCount.bind(logger));
document.querySelector('button').addEventListener('click', logger.updateCount.bind(logger));
我们巧妙地使用了方便的 .bind() 函数来创建一个新的函数,而将它的作用域绑定为 logger 对象。
SETTIMEOUT
如果你使用过模板引擎(比如Handlebars)或者尤其使用过某些MV*框架(从我的经验我只能谈论Backbone.js),那么你也许知道下面讨论的关于在渲染模板之后立即访问新的DOM节点时会遇到的问题。
假设我们想要实例化一个jQuery插件:
var myView = {
template: '/* 一个包含 &select /& 的模板字符串*/',
$el: $('#content'),
afterRender: function () {
this.$el.find('select').myPlugin();
render: function () {
this.$el.html(this.template());
this.afterRender();
myView.render();
1234567891011121314151617
var myView = {&&&&&template: '/* 一个包含 &select /& 的模板字符串*/',&&&&&$el: $('#content'),&&&&&afterRender: function () {&&&&&&&&this.$el.find('select').myPlugin();&&&&},&&&&&render: function () {&&&&&&&&this.$el.html(this.template());&&&&&&&&this.afterRender();&&&&}}&myView.render();
你或许发现它能正常工作——但并不是每次都行,因为里面存在着问题。这是一个竞争的问题:只有先到达的才能获胜。有时候是渲染先到,而有时候是插件的实例化先到。【译者注:如果渲染过程还没有完成(DOM Node还没有被添加到DOM树上),那么find(‘select’)将无法找到相应的节点来执行实例化。】
现在,或许并不被很多人知晓,我们可以使用基于 setTimeout() 的 来解决问题。
我们稍微改写一下我们的代码,就在DOM节点加载后再安全的实例化我们的jQuery插件:
afterRender: function () {
this.$el.find('select').myPlugin();
render: function () {
this.$el.html(this.template());
setTimeout(this.afterRender, 0);
123456789101112
//&&&&&afterRender: function () {&&&&&&&&this.$el.find('select').myPlugin();&&&&},&&&&&render: function () {&&&&&&&&this.$el.html(this.template());&&&&&&&&setTimeout(this.afterRender, 0);&&&&&&&&&&&&}&//
然而,我们获得的是 函数 .afterRender() 不能找到 的错误信息。
我们接下来要做的,就是将.bind()使用到我们的代码中:
afterRender: function () {
this.$el.find('select').myPlugin();
render: function () {
this.$el.html(this.template());
setTimeout(this.afterRender.bind(this), 0);
123456789101112
//&&&&&afterRender: function () {&&&&&&&&this.$el.find('select').myPlugin();&&&&},&&&&&render: function () {&&&&&&&&this.$el.html(this.template());&&&&&&&&setTimeout(this.afterRender.bind(this), 0);&&&&&&&&&&&&}&//
现在,我们的 afterRender() 函数就能够在正确的上下文环境中执行了。
梳理基于 QUERYSELECTORALL的事件绑定
如今的DOM API引入了很多非常有用的方法,比如 querySelector, querySelectorAll 和 classList接口,这些方法给DOM API带来了非常显著的进步。
然而,迄今为止并没有一个真正的原生的为 NodeList 添加事件的方法。于是我们最终从 Array.prototype中剽窃了 forEach 方法来完成遍历,例如:
Array.prototype.forEach.call(document.querySelectorAll('.klasses'), function(el){
el.addEventListener('click', someFunction);
Array.prototype.forEach.call(document.querySelectorAll('.klasses'), function(el){&&&&el.addEventListener('click', someFunction);});
仍然,我们可以做的更好,通过使用我们的好朋友 .bind()。
var unboundForEach = Array.prototype.forEach,
forEach = Function.prototype.call.bind(unboundForEach);
forEach(document.querySelectorAll('.klasses'), function (el) {
el.addEventListener('click', someFunction);
var unboundForEach = Array.prototype.forEach,&&&&forEach = Function.prototype.call.bind(unboundForEach);&forEach(document.querySelectorAll('.klasses'), function (el) {&&&&el.addEventListener('click', someFunction);});
现在,我们拥有了一个简洁的遍历DOM节点的函数。
正如你所看到的,.bind() 函数可以巧妙地运用于很多不同的用途,同时可以精简现有的代码。但愿这篇概述的内容,能够在你想在代码中使用.bind()(如果需要的话)时派上用场,并且帮助你更好地驾驭改变this值所带来的好处。
关于作者:
可能感兴趣的话题
我觉得这里bind有点问题
如果有[args]就会出问题了.源码不应该是这样的
关于伯乐在线博客
在这个信息爆炸的时代,人们已然被大量、快速并且简短的信息所包围。然而,我们相信:过多“快餐”式的阅读只会令人“虚胖”,缺乏实质的内涵。伯乐在线内容团队正试图以我们微薄的力量,把优秀的原创文章和译文分享给读者,为“快餐”添加一些“营养”元素。
新浪微博:
推荐微信号
(加好友请注明来意)
– 好的话题、有启发的回复、值得信赖的圈子
– 分享和发现有价值的内容与观点
– 为IT单身男女服务的征婚传播平台
– 优秀的工具资源导航
– 翻译传播优秀的外文文章
– 国内外的精选文章
– UI,网页,交互和用户体验
– 专注iOS技术分享
– 专注Android技术分享
– JavaScript, HTML5, CSS
– 专注Java技术分享
– 专注Python技术分享
& 2017 伯乐在线Bootstrap每天必学之工具提示(Tooltip)插件
投稿:lijiao
字体:[ ] 类型:转载 时间:
Bootstrap每天必学之工具提示(Tooltip)插件,工具提示就是通过鼠标移动选定在特定的元素上时,显示相关的提示语,感兴趣的小伙伴们可以参考一下
当您想要描述一个链接的时候,工具提示(Tooltip)就显得非常有用。工具提示(Tooltip)插件是受 Jason Frame 写的 jQuery.tipsy 的启发。工具提示(Tooltip)插件做了很多改进,例如不需要依赖图像,而是改用 CSS 实现动画效果,用 data 属性存储标题信息。
如果您想要单独引用该插件的功能,那么您需要引用 tooltip.js。或者,正如 一章中所提到,您可以引用 bootstrap.js 或压缩版的 bootstrap.min.js。
工具提示(Tooltip)插件根据需求生成内容和标记,默认情况下是把工具提示(tooltip)放在它们的触发元素后面。您可以有以下两种方式添加工具提示(tooltip):
1、通过 data 属性:如需添加一个工具提示(tooltip),只需向一个锚标签添加 data-toggle="tooltip" 即可。锚的 title 即为工具提示(tooltip)的文本。默认情况下,插件把工具提示(tooltip)设置在顶部。
&a href="#" data-toggle="tooltip" title="Example tooltip"&请悬停在我的上面&/a&
2、通过 JavaScript:通过 JavaScript 触发工具提示(tooltip):
$('#identifier').tooltip(options)
工具提示(Tooltip)插件不像之前所讨论的下拉菜单及其他插件那样,它不是纯 CSS 插件。如需使用该插件,您必须使用 jquery 激活它(读取 javascript)。使用下面的脚本来启用页面中的所有的工具提示(tooltip):
$(function () { $("[data-toggle='tooltip']").tooltip(); });
有一些选项是通过 Bootstrap 数据 API(Bootstrap Data API)添加或通过 JavaScript 调用的。下表列出了这些选项:
三.工具提示
//基本实例
&a href="#" data-toggle="tooltip" title="超文本标识符"&HTML5&/a&
//JS 部分需要声明
$('#section').tooltip();
工具提示有很多属性来配置提示的显示,具体如下:
&a href="#" rel="tooltip" data-toggle="tooltip" title="超文本标识符"
data-animation="false"
data-html="true"
data-placement="auto"
data-selector="a[rel=tooltip]"
data-trigger="click"
data-delay="500"
data-template="&b&123&/b&"
&HTML5&/a&
JavaScript 方式直接去掉前面的 data 即可。包括:animation、html、placement、selector、original-title、title、trigger、delay、container 和 template 等属性。
//JavaScript 方式
$('#section a').tooltip({
show : 500,
hide : 100,
container : 'body'
JavaScript 有四个方法:show、hide、toggle 和 destroy 四种。
$('#section a').tooltip('show');
$('#section a').tooltip('hide');
//反转显示和隐藏
$('#section a').tooltip('toggle');
//隐藏并销毁
$('#section a').tooltip('destroy');
Tooltip 中事件有四种。
//事件,其他雷同
$('#select a').on('show.bs.tooltip', function() {
alert('调用 show 时触发!');
本文系列教程整理到: 专题中,欢迎点击学习。
如果大家还想深入学习,可以点击进行学习,再为大家附3个精彩的专题:
以上就是本文的全部内容,希望对大家的学习有所帮助。
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具wpf 模板选择器DataTemplateSelector及动态绑定使用教程 | 熊窝窝
其实也说不上算是教程了,只是把自己学习的代码拿出来分享一下,同时方便以后遇到类似问题的时候翻一下。
MSDN里如是说:
通常,如果有多个 DataTemplate 可用于同一类型的对象,并且您希望根据每个数据对象的属性提供自己的逻辑来选择要应用的 DataTemplate,则应创建 DataTemplateSelector。请注意,如果具有不同类型的对象,则可以对 DataTemplate 设置 DataType 属性。如果您执行了此操作,则无需创建 DataTemplateSelector。此外,如果对象类型相同但属性不同,也可以考虑使用 DataTrigger 或数据转换器。
通俗讲,就是根据不同的数据选择不同的模板。接下来,我用一个例子来讲述DataTemplateSelector和动态绑定的使用方法。
先看例子的UI:
一个Listbox三个button,listbox显示一个集合的数据,第一个button “change”点击后可以切换与listbox绑定的集合,第二个button给PersonCollection添加person实例,第三个button给AnimalCollection添加animal实例。
默认情况下listbox与PersonCollection绑定,程序启动后,点击Add person按钮会向PersonCollection添加一个person实例,listbox会显示该集合下数据,如果person类的gender属性为Female,则只显示name属性,并把边框改成蓝色。点击change后,listbox与AnimalCollection绑定,显示AnimalCollection数据,同样,Add animal添加animal实例,如果第二个属性不是4,则只显示animal的type属性,并修改边框为蓝色。
下面讲实现
第一步:建两个类,一个person,一个animal,这就是每个listbox item将来要显示的数据。
1234567891011121314151617181920212223242526272829303132333435363738394041424344//person类
& & public class person : INotifyPropertyChanged
& & {
& & & & public event PropertyChangedEventHandler PropertyChanged;
& & & & private string _name;
& & & & public string name
& & & & {
& & & & & & get
& & & & & & {
& & & & & & & & return _name;
& & & & & & }
& & & & & & set
& & & & & & {
& & & & & & & & if (value != _name)
& & & & & & & & {
& & & & & & & & & & _name = value;
& & & & & & & & & & prochanged(&name&);
& & & & & & & & }
& & & & & & }
& & & & }
& & & & private string _gender;
& & & & public string gender
& & & & {
& & & & & & get
& & & & & & {
& & & & & & & & return _gender;
& & & & & & }
& & & & & & set
& & & & & & {
& & & & & & & & if (value != _gender)
& & & & & & & & {
& & & & & & & & & & _gender = value;
& & & & & & & & & & prochanged(&gender&);
& & & & & & & & }
& & & & & & }
& & & & }
& & & & private void prochanged(string info)
& & & & {
& & & & & & if (PropertyChanged != null)
& & & & & & {
& & & & & & & & PropertyChanged(this,
PropertyChangedEventArgs(info));
& & & & & & }
& & & & }
& & }
注意到这里,实现了INotifyPropertyChanged接口,需要引用命名空间ponentModel.因为我希望这些属性改变的时候,listboxitem能自动更新,关于INotifyPropertyChanged接口,请看我另一篇日志。
另一个类,animal与person基本类似,只是把person类里的属性:name和gender改成了type和legs。这里我就不贴代码了。
第二步:创建类DataContainer,包含两个集合,存储animal和person实例。代码:
12345678910& & public class DataContainer
& & {
& & & & public &ObservableCollection&person& PersonCollection { get;set; }
& & & & public &ObservableCollection&animal& AnimalCollection { get; set; }
& & & & public DataContainer()
& & & & {
& & & & & & PersonCollection =
ObservableCollection&person&();
& & & & & & AnimalCollection =
ObservableCollection&animal&();
& & & & }
& & }
我用了ObservableCollection,因为ObservableCollection已经实现了INotifyPropertyChanged接口,所以如果集合的项增删的时候UI会自动更新。(using System.Collections.ObjectM//ObservableCollection)
注意:假设最上面第一段代码person类里面,没有实现INotifyPropertyChanged接口,而这里仍然使用ObservableCollection来存储person列表的话,PersonCollection 里的项增加或删除时,UI的listbox也会相应的增删,但是当你想修改PersonCollection里某一个person实例的属性,比如gender由male变成female时,UI并不会更新,因为PersonCollection 并没变。所以,当你希望改变UI listbox item里某个person的属性时,person类就需要实现INotifyPropertyChanged接口。
第三步:定义数据模板。
当然首先在窗口里把需要的listbox和button放好。我的XAML代码如下:
1234567& & &Grid&
& & & & &ListBox Margin=&12,12,12,60& Name=&listBox1& & HorizontalContentAlignment =&Stretch& ItemTemplateSelector=&{StaticResource mytemplate_selector}&&
& & & & &/ListBox&
& & & & &Button Height=&23& HorizontalAlignment=&Left& Margin=&12,0,0,12& Name=&Change& VerticalAlignment=&Bottom& Width=&75& Click=&Change_Click&&Change&/Button&
& & & & &Button Height=&23& Margin=&120,0,109,12& Name=&addperson& VerticalAlignment=&Bottom& Click=&addperson_Click&&Add person&/Button&
& & & & &Button Height=&23& HorizontalAlignment=&Right& Margin=&0,0,12,12& Name=&addanimal& VerticalAlignment=&Bottom& Width=&75& Click=&addanimal_Click&&Add animal&/Button&
& & &/Grid&
吃饭去了,回来再写……
继续,上面的XAML里的3个button没什么好说的,listbox里,最重要的一句是:ItemTemplateSelector=”{StaticResource mytemplate_selector}”,从字面意思理解,就是把一个叫做mytemplate_selector的静态资源,做为listbox的模板选择器。所以,接下来,定义我们需要资源,包括一个模板选择器和四个数据模板。模板选择器就是这里的mytemplate_selector,四个模板,person和animal各两个,通过模板选择器选择使用哪一个。
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253& & &Window.Resources&
& & & & &local:MyDataTemplateSelector x:Key=&mytemplate_selector& /&
& & & & &DataTemplate x:Key =&person_template&&
& & & & & & &Border &Name=&myborder& BorderBrush=&Blue& Padding=&5& Margin=&2& BorderThickness=&1&&
& & & & & & &StackPanel&
& & & & & & & & &TextBlock &Text=&{Binding Path=name}&&&/TextBlock &
& & & & & & & & &TextBlock &Text=&{Binding Path=gender}&&&/TextBlock &
& & & & & & &/StackPanel&
& & & & & & &&/Border&
& & & & & & &DataTemplate.Triggers&
& & & & & & & & &DataTrigger &Value=&Male& Binding=&{Binding Path=gender}&& & & & & &
& & & & & & & & & & &Setter TargetName=&myborder& Property=&BorderBrush& Value=&Red& /&
& & & & & & & & &/DataTrigger&
& & & & & & &/DataTemplate.Triggers&
& & & & &/DataTemplate&
& & & & &DataTemplate x:Key=&male_template&&
& & & & & & &DataTemplate.Resources&
& & & & & & & & &Style TargetType=&TextBlock&&
& & & & & & & & & & &Setter Property=&FontSize& Value=&20& /&
& & & & & & & & &/Style&
& & & & & & &/DataTemplate.Resources&
& & & & & & &Border &Name=&myborder_male& BorderBrush=&Blue& Padding=&5& Margin=&2& BorderThickness=&1&&
& & & & & & & & &DockPanel&
& & & & & & & & & & &TextBlock Text=&{Binding Path=name}&/&
& & & & & & & & &/DockPanel&
& & & & & & &/Border&
& & & & &/DataTemplate&
& & & & &DataTemplate x:Key =&animal_template&&
& & & & & & &Border &Name=&myborder& BorderBrush=&Blue& Padding=&5& Margin=&2& BorderThickness=&1&&
& & & & & & & & &StackPanel&
& & & & & & & & & & &TextBlock &Text=&{Binding Path=type}&&&/TextBlock &
& & & & & & & & & & &TextBlock &Text=&{Binding Path=legs}&&&/TextBlock &
& & & & & & & & &/StackPanel&
& & & & & & &/Border&
& & & & & & &DataTemplate.Triggers&
& & & & & & & & &DataTrigger &Value=&4& Binding=&{Binding Path=legs}&&
& & & & & & & & & & &Setter TargetName=&myborder& Property=&BorderBrush& Value=&Red& /&
& & & & & & & & &/DataTrigger&
& & & & & & &/DataTemplate.Triggers&
& & & & &/DataTemplate&
& & & & &DataTemplate x:Key=&fourlegs_template&&
& & & & & & &DataTemplate.Resources&
& & & & & & & & &Style TargetType=&TextBlock&&
& & & & & & & & & & &Setter Property=&FontSize& Value=&20& /&
& & & & & & & & &/Style&
& & & & & & &/DataTemplate.Resources&
& & & & & & &Border &Name=&myborder_male& BorderBrush=&Blue& Padding=&5& Margin=&2& BorderThickness=&1&&
& & & & & & & & &DockPanel&
& & & & & & & & & & &TextBlock Text=&{Binding Path=type}&/&
& & & & & & & & &/DockPanel&
& & & & & & &/Border&
& & & & &/DataTemplate&
& & &/Window.Resources&
分析前面的XAML,在里面,我们共定义了五个资源,我简单分析一下前三个,后面两个跟第二个、第三个差不多,就不说多了。
第一个资源,定义了一个模板选择器,使用CS文件里的MyDataTemplateSelector类来选择模板。第二个资源,person_template, StackPanel里定义了普通的模板,显示person的name和gender,DataTrigger里定义了一个触发器,当gender为Male的时候,将item的border变成红色。这就是前面UI里不同的边框色的实现关键点。第三个资源male_template,定义了一个Male专用的模板,字体20号,只显示name。person_template模板里,边框颜色的变换通过DataTrigger就能实现,因为要修改的属性是在模板里存在的。但是当你想修改一些模板里不存的属性或者对于gender = male时使用另外完全不同的模板,那就要用到模板选择器了。下面分析前面提到的模板选择器,看着比较多,其实很简单,忍一忍认真点儿看完,你就能有更多收获。
12345678910111213141516171819202122232425262728293031323334353637//必须继承自DataTemplateSelector
&public class MyDataTemplateSelector:DataTemplateSelector
& & {
& & & & //覆盖SelectTemplate函数
& & & & public override DataTemplate SelectTemplate(object item, DependencyObject container)
& & & & {
& & & & & & Window win = Application.Current.MainWindow;
& & & & & & //当前正在显示的是person类数据时:
& & & & & & if (item != null && item
person)
& & & & & & { & & & & & & &
& & & & & & & & person p = item as person;
& & & & & & & & //如果gender是male,将person_template做为现在的模板
& & & & & & & & if (p.gender==&Male&)
& & & & & & & & {
& & & & & & & & & & return win.FindResource(&person_template&) as DataTemplate;
& & & & & & & & }
& & & & & & & & //否则就使用male_template
& & & & & & & & else
& & & & & & & & {
& & & & & & & & & & return win.FindResource(&male_template&) as DataTemplate;
& & & & & & & & }
& & & & & & }
& & & & & & else if(item != null && item
animal)
& & & & & & {
& & & & & & & & animal a = item as animal;
& & & & & & & & if (a.legs==4)
& & & & & & & & {
& & & & & & & & & & return win.FindResource(&animal_template&) as DataTemplate;
& & & & & & & & }
& & & & & & & & else
& & & & & & & & {
& & & & & & & & & & return win.FindResource(&fourlegs_template&) as DataTemplate;
& & & & & & & & }
& & & & & & }
& & & & & & return null;
& & & & }
& & }
程序初初始化的时候:
1234567891011& & & & private bool isPersonDisplaying;
& & & & private DataContainer dc;
& & & & public Window1()
& & & & {
& & & & & & InitializeComponent();
& & & & & & //表示当前正在显示的数据。默认显示person
& & & & & & isPersonDisplaying = true;
& & & & & & dc =
DataContainer();
& & & & & & //指定数据源
& & & & & & listBox1.ItemsSource = dc.PersonCollection;
& & & & }
三个按钮的函数,change:
1234567891011121314151617private void Change_Click(object sender, RoutedEventArgs e)
& & & & {
& & & & & & changeBindingPath();
& & & & }
& & & & private void changeBindingPath()
& & & & {
& & & & & & if (isPersonDisplaying)
& & & & & & {
& & & & & & & & listBox1.ItemsSource = dc.AnimalCollection;
& & & & & & & & isPersonDisplaying = false;
& & & & & & }
& & & & & & else
& & & & & & {
& & & & & & & & listBox1.ItemsSource = dc.PersonCollection;
& & & & & & & & isPersonDisplaying = true;
& & & & & & }
& & & & }
这里实现不同数据源的切换,当数据源变换的时候,WPF会调用前面我们定义的模板选择器,选择正确的模板。
两个增加数据的函数:
12345678910111213141516&private void addperson_Click(object sender, RoutedEventArgs e)
& & & & {
& & & & & & person p =
person();
& & & & & & p.name = &PersonName& + System.DateTime.Now.Second.ToString();
& & & & & & string gender = (System.DateTime.Now.Second%2)==1?&Male&:&Female&;
& & & & & & p.gender = gender;
& & & & & & dc.PersonCollection.Add(p);
& & & & }
& & & & private void addanimal_Click(object sender, RoutedEventArgs e)
& & & & {
& & & & & & animal a =
animal();
& & & & & & a.type = &AnimalType& + System.DateTime.Now.Second.ToString();
& & & & & & a.legs = (System.DateTime.Now.Second % 2) == 1 ? 2 : 4;
& & & & & & dc.AnimalCollection.Add(a);
& & & & }
表达能力一般,水平一般,大家见谅。源代码我打了个包,,编译环境:vs2008。
本条目发布于。属于分类。作者是。
有人回复时邮件通知我
2017年一月 &(2)
2016年七月 &(1)
2016年四月 &(1)
2016年二月 &(1)
2016年一月 &(5)
2015年十一月 &(2)
2015年十月 &(84)
2015年五月 &(2)
2015年四月 &(2)
2015年二月 &(1)
2015年一月 &(2)
2014年十二月 &(4)
2014年十一月 &(3)
2014年十月 &(1)
2014年九月 &(4)
2014年八月 &(1)
2014年四月 &(4)
2014年三月 &(8)
2014年二月 &(1)
2014年一月 &(1)
2013年三月 &(2)
2013年二月 &(2)
2012年十二月 &(2)
2012年十一月 &(2)
2012年九月 &(2)
2012年八月 &(3)
2012年七月 &(3)
2012年六月 &(2)
2012年五月 &(1)
2012年四月 &(2)
2012年二月 &(1)
2012年一月 &(1)
2011年十月 &(1)
2011年八月 &(1)
2011年七月 &(2)
2011年六月 &(14)
2011年五月 &(6)
2011年四月 &(9)
2011年三月 &(2)
2011年一月 &(7)
2010年十二月 &(8)
2010年十一月 &(1)
2010年十月 &(4)
2010年九月 &(1)
2010年八月 &(2)
2010年七月 &(3)
2010年六月 &(10)
2010年五月 &(6)
2010年四月 &(15)
2010年三月 &(17)
2010年二月 &(15)
2010年一月 &(26)
2009年十二月 &(22)
2009年十一月 &(35)
2009年十月 &(18)
2009年九月 &(5)
2009年八月 &(3)
2009年七月 &(1)
2009年六月 &(1)
2009年五月 &(2)
2009年四月 &(7)

我要回帖

更多关于 不论时代发生多大变化 的文章

 

随机推荐