动态载入数据的无刷新TreeView控件(4)

  前三天我们把TreeView给显示出来了,不过光是显示显然是不够的。TreeView的UI还需要根据用户的各种操作和不同的属性设置产生不同的效果变化,比如:Actived、Selected、Checked等。下面就来设计并实现TreeView的UI动态更新问题。

    对于控件开发,不管是Web上的还是WinForm上,使用鼠标和键盘来触发的UI更新和使用程序代码来触发更新是同等地位的。所以我们在设计中最好不要在事件处理函数里面去直接的更新控件UI,为什么呢?因为这样的更新是单向服务的(虽然可以在程序中去调用HTML元素的事件回调,不过语法上太蹩脚了),当我们需要在程序中去更新控件UI,比如设置Selected状态,就需要再写一套代码来从程序的角度去更新UI元素的属性。这时我们会发现前面那种单向服务的代码,其实是完全可以被后者包括(在功能上)的。继续说Selected,当我们用鼠标点击TreeNode时,我们可以从事件响应代码中直接拿到event.srcElement(这就是显示TreeNode的HTML元素),我们如果在此时修改这个元素的属性来显示Selected状态,很容易。可是如果我们还需要在程序中去调用TreeNode.SetSelected( true)来得到Selected效果时,前面所说的单向服务的代码就都被后者(SetSelected)包含了。

    哦,那么我们就实现n个方法,比如:SetActived(bool)、SetSelected(bool)、SetChecked(bool),在这些方法中去分别修改控件UI元素属性。由于我们在JS控件中,需要在脚本对象和DHMTL对象中来回引用和查找,并且有些状态的UI的显示还存在优先级的问题(比如Checked和Selected都需要文字颜色变化,但Selected优先级高于Checked)。所以我们也不在每个SetXXX函数中去更新UI元素的属性,而是使用一个统一的函数,来对整个控件的UI更新作出处理。于是我们定义了一个ApplyUIChange()函数,在这里面处理所有和UI呈现有关属性的处理,并具体修改UI元素的属性。

    SetXXX方法实现为:
None.gif TreeNode.prototype.SetChecked =  function(isCheck)
None.gif {
None.gif     var innerCache =  this.m_Tree.m_InnerCache;
None.gif     if ( isCheck )
None.gif    {
None.gif         if ( !innerCache.m_Checkeds.Contains( this) ) 
None.gif        {
None.gif            innerCache.m_Checkeds.Add( this);
None.gif        }
None.gif    }
None.gif     else
None.gif    {
None.gif        innerCache.m_Checkeds.Remove( this);
None.gif    }    
None.gif     this.m_Checked = isCheck;
None.gif     this.ApplyUIChange();
None.gif };
None.gif
None.gif TreeNode.prototype.SetSelected =  function(isSelected)
None.gif {
None.gif     var innerCache =  this.m_Tree.m_InnerCache;
None.gif     if ( isSelected )
None.gif    {
None.gif         if ( !innerCache.m_Selecteds.Contains( this) ) 
None.gif        {
None.gif             innerCache.m_Selecteds.Add( this);
None.gif        }
None.gif    }
None.gif     else
None.gif    {
None.gif        innerCache.m_Selecteds.Remove( this);
None.gif    }    
None.gif     this.m_Selected = isSelected;
None.gif     this.ApplyUIChange();
None.gif };

    它们只负责维护 控件对象的属性状态,所有的控件的UI相关操作交由 this.ApplyUIChange()去处理。这个设计也和WinForm控件中修改属性后的显示调用Invalidate()的设计类似,一切的UI更新都在OnPaint中做。innerCache相关操作在这里不用关心,那是用来记录TreeView实例中被Checked和Selected的Nodes用的,以后再讲。

    ApplyUIChange代码实现如下:
None.gif TreeNodeBase.prototype.ApplyUIChange =  function()
None.gif {
None.gif      if (  this.m_Element.CheckBox )
None.gif     {
None.gif          this.m_Element.CheckBox.checked =  this.m_Checked;
None.gif     } 
None.gif      var elmtNode =  this.m_Element.Content;
None.gif      if (  this.m_Selected )
None.gif     {
None.gif         elmtNode.style.color =  this.Styles('SelectedForeColor');
None.gif         elmtNode.style.background =  this.Styles('SelectedBackColor');
None.gif     }
None.gif      else
None.gif     {
None.gif          if (  this.m_Checked )
None.gif         {
None.gif             elmtNode.style.color =  this.Styles('CheckedForeColor');
None.gif             elmtNode.style.background =  this.Styles('CheckedBackColor');
None.gif         }
None.gif          else
None.gif         {    
None.gif             elmtNode.style.color =  this.Styles('NormalForeColor');
None.gif             elmtNode.style.background =  this.Styles('NormalBackColor');
None.gif         }
None.gif     }
None.gif      if (  this.m_IsActive )
None.gif     {
None.gif         elmtNode.runtimeStyle.textDecoration = 'underline';
None.gif     }
None.gif      else
None.gif     {
None.gif         elmtNode.runtimeStyle.textDecoration  = '';
None.gif     }
None.gif };

    在这个方法中,它只用关心属性间的优先级和对UI元素属性的修改,同时这也是程序中唯一修改HTML元素属性的地方。不过本控件中Node的子树的Expand和Collapse的UI元素属性更新没有放在这里,这时因为放在它们独自的方法中也很清晰(不存在和其它UI显示冲突的问题)。也就是说我们虽然有设计原则,不过有时可以使用别的简便方法实现时,也不用太拘泥于原则。设计本身就是妥协,而且我们实际需要的就是简便清晰的实现,而不是要完美的原则。
    
    附各中TreeView的外观样式变化:
    TreeView-3.gif

    to be continued . . .


本文转自博客园鸟食轩的博客,原文链接:http://www.cnblogs.com/birdshome/,如需转载请自行联系原博主。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值