动态载入数据的无刷新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方法实现为:
 TreeNode.prototype.SetChecked =  function(isCheck)
 {
     var innerCache =  this.m_Tree.m_InnerCache;
     if ( isCheck )
    {
         if ( !innerCache.m_Checkeds.Contains( this) ) 
        {
            innerCache.m_Checkeds.Add( this);
        }
    }
     else
    {
        innerCache.m_Checkeds.Remove( this);
    }    
     this.m_Checked = isCheck;
     this.ApplyUIChange();
 };

 TreeNode.prototype.SetSelected =  function(isSelected)
 {
     var innerCache =  this.m_Tree.m_InnerCache;
     if ( isSelected )
    {
         if ( !innerCache.m_Selecteds.Contains( this) ) 
        {
             innerCache.m_Selecteds.Add( this);
        }
    }
     else
    {
        innerCache.m_Selecteds.Remove( this);
    }    
     this.m_Selected = isSelected;
     this.ApplyUIChange();
 };

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

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

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

    to be continued . . .


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

目录
相关文章
|
C#
WPF通过代码动态的加载样式
原文:WPF通过代码动态的加载样式 tabitem.SetResourceReference(TabItem.StyleProperty, "mainTabItemStyle"); tabitem.Content = new Goods.GoodsMain();
1211 0
|
前端开发 容器
用MVVM模式开发中遇到的零散问题总结(5)——将动态加载的可视元素保存为图片的控件,Binding刷新的时机
原文:用MVVM模式开发中遇到的零散问题总结(5)——将动态加载的可视元素保存为图片的控件,Binding刷新的时机       在项目开发中经常会遇到这样一种情况,就是需要将用户填写的信息排版到一张表单中,供打印或存档。
829 0
|
JavaScript 前端开发 安全
扩展EasyUI在页面中马上显示选中的本地图片
在编写前台页面的时候,有时须要将选中的图片夹杂着其它信息一起上传到服务端,在选着本地图片的时候,为了获得更好的效果,须要将该图片显示在页面上。
2514 0