当前位置: 首页 > news >正文

河间网站建设公司四川网站建设公司

河间网站建设公司,四川网站建设公司,缅甸网站建设,怎么建设一个音乐网站1.前言继上一篇《WPF应用基础篇---TreeView》的发布之后#xff0c;有部分朋问我关于里面一些基础应用的问题#xff0c;可能是我写得不够详细#xff0c;所以在这里#xff0c;我想再次那文章中的案例来谈谈初步体验数据驱动之美#xff0c;摆脱旧WinForm编程习惯(靠触发…     1.前言  继上一篇《WPF应用基础篇---TreeView》的发布之后有部分朋问我关于里面一些基础应用的问题可能是我写得不够详细所以在这里我想再次那文章中的案例来谈谈初步体验数据驱动之美摆脱旧WinForm编程习惯(靠触发事件来实现界面的变化)。 2.背景     我们看看以下案例图片的功能如何实现       图1-1(WinForm两态树)           图1-2(WPF三态树)  如果我们还处在习惯于WinForm开发的时候,我们首先关注的是我们需要重写Tree控件在上一篇文章中有提到过这里就不再重复。然后当我们布局和设计好数据结构后我们关心的自然就是选中的时候要做什么我们首先会考虑到为树节点添加事件来处理相应的逻辑处理。大致实现以下几个步骤简单的分析把sender或者e参数转换为TreeNode从TreeNode中的Tag数据根据Tag的类型转换为具体数据判断TreeNode选中的状态更改Tag实例的属性的状态如IsSelected根据需求比如          全部选中--父节点CheckBox打钩 同时修改父节点数据根据当前修改所有子节点状态          全部未选中--父节点CheckBox为空 同时修改父节点数据根据当前修改所有子节点状态  WinForm具体代码实现两态树View Code /// summary        /// 设置父节点状态        /// /summary        /// param namenode/param        public void SetParentNodeStatus(TreeNode node)        {            if (node.Parent ! null)            {                bool isChecked true;                foreach (TreeNode data in node.Parent.Nodes)                {                    if (!data.Checked)                    {                        isChecked false;                        break;                    }                }                if (isChecked)                {                    node.Parent.Checked true;                    if(node.Parent.Parent!null)                    {                        SetParentNodeStatus(node.Parent);                    }                }                else                {                    node.Parent.Checked false;                }            }        }        /// summary        /// 设置孩子节点状态        /// /summary        /// param namenode/param        public void SetChildNodeStatus(TreeNode node)        {            if (node.Nodes!null)            {                foreach (TreeNode data in node.Nodes)                {                    data.Checked node.Checked;                    if (data.Nodes!null)                    {                        SetChildNodeStatus(data);                    }                }            }        }        /// summary        /// 树节点被选中后 触发的事件        /// /summary        /// param namesender/param        /// param namee/param        private void treeView1_AfterCheck(object sender, TreeViewEventArgs e)        {           //isClick是全局变量              //是为了解决无限递归而是用的一个标志            if (!isClick)                             {                return;            }            isClick false;            TreeNode node e.Node;                        if (node.Parent ! null)            {                SetParentNodeStatus(e.Node);            }            if (node.Nodes ! null)            {                SetChildNodeStatus(node);            }            isClick true;        }   而当我们开始慢慢采用WPF之后我们的编程习惯会发生了很大的变化我们开始有点对触发事件来改变逻辑和界面变化事件驱动的做法感到反感。解决上面的问题我们只需要靠一个接口的帮助就能实现两态树的功能。实现INotifyPropertyChanged解口当数据改变时修改父节点和相应子节点的状态然后把数据绑定到界面上去。   WPF具体代码实现两态树  View Code //是否被选中        private bool? isSelected;        public bool? IsSelected         {            get { return isSelected; }            set            {                if (isSelected ! value)                {                    isSelected  value;                       ChangeChildNodes(this);                    ChangedParentNodes(this);                    NotifyPropertyChanged(IsSelected);                }            }        }/// summary        /// 向下遍历,更改孩子节点状态        /// 注意这里的父节点不是属性而是字段        /// 采用字段的原因是因为不想让父节点触发访问器而触发Setter        /// /summary        /// param nameCurrentNode/param        public void ChangeChildNodes(Device CurrentNode)        {            if (CurrentNode.ChildNodes ! null)            {                foreach (var data in CurrentNode.ChildNodes)                {                    data.isSelected  CurrentNode.IsSelected;                    data.NotifyPropertyChanged(IsSelected);                    if (data.ChildNodes ! null)                    {                        data.ChangeChildNodes(data);                    }                }            }        }        /// summary        /// 向上遍历,更改父节点状态        /// 注意这里的父节点不是属性而是字段        /// 采用字段的原因是因为不想让父节点触发访问器而触发Setter        /// /summary        /// param nameCurrentNode/param        public void ChangedParentNode(Device CurrentNode)        {            if (CurrentNode.ParentNode ! null)            {                bool isCheck  true;                foreach (var data in CurrentNode.ParentNode.ChildNodes)                {                    if (data.IsSelected ! true)                    {                        isCheck  false;                        break;                    }                }                CurrentNode.parentNode.isSelected  isCheck;                CurrentNode.parentNode.NotifyPropertyChanged(IsSelected);            }        }  从两段代码可以看出WinForm实现代码是事件驱动首先触发一个事件然后进行一些逻辑判断而且还需要借助全部变量IsClick来防止代码无限递归。而WPF的实现则是靠数据驱动数据变化了然后才调用方法来更改数据的相应状态。最后才通知界面刷新数据。其实可以看出现在的需求很简单就是根据节点选中状态操作树但是如果我的需求变化了例如图1-2的需求一样如果我需要打钩的时候操作按钮的状态比如打钩就连接不打钩则断开。WinForm的话又要在代码中做一些逻辑判断这很容易实现但是如果我断开按钮按下的时候只能点击连接这时候WinForm的事件就要做很多逻辑处理如果需求要求的功能多的话事件的后台代码将越来越复杂最后导致逻辑混乱。而WPF实现的话则是根据数据变化而且在界面上显示当我点击的时候修改下数据的状态则可以。后台无需要做太多的处理这样代码结构和逻辑会变得相对清晰。 3.三态树具体实现  这里将为大家介绍下三态树在WPF中的实现也是对上一篇文章的补充。本案例是在基于MVVM的基础上实现的。要实现图1-2(三态树)只需要做以下两个步骤。定义好数据结构并在数据上通过实现INotifyPropertyChanged接口来属性变化后通知View刷新数据。把想对应的属性Binding到View的控件上。    数据结构实体代码  View Code /// summary    /// 设备基类    /// /summary    public class Device:INotifyPropertyChanged    {        //是否被选中        private bool? isSelected;        public bool? IsSelected         {            get { return isSelected; }            set            {                if (isSelected ! value)                {                    isSelected  value;                       ChangeChildNodes(this);                    ChangedParentNodes(this);                    NotifyPropertyChanged(IsSelected);                }            }        }                private DeviceStatus status;        public DeviceStatus Status        {            get { return status; }            set            {                if (status ! value)                {                    status  value;                    NotifyPropertyChanged(Status);                }            }        }        public string Name { get; set; }        public string ImageUrl{get;set;}        private ListDevice childNodes;        public ListDevice ChildNodes        {            get { return childNodes; }            set            {                if (childNodes ! value)                {                    childNodes  value;                    NotifyPropertyChanged(ChildNodes);                }            }        }        private Device parentNode;        public Device ParentNode        {            get { return parentNode; }            set            {                if (parentNode ! value)                {                    parentNode  value;                    NotifyPropertyChanged(ParentNode);                }            }        }        /// summary        /// 向下遍历,更改孩子节点状态        /// 注意这里的父节点不是属性而是字段        /// 采用字段的原因是因为不想让父节点触发访问器而触发Setter        /// /summary        /// param nameCurrentNode/param        public void ChangeChildNodes(Device CurrentNode)        {            if (CurrentNode.ChildNodes ! null)            {                foreach (var data in CurrentNode.ChildNodes)                {                    data.isSelected  CurrentNode.IsSelected;                    data.NotifyPropertyChanged(IsSelected);                    if (data.ChildNodes ! null)                    {                        data.ChangeChildNodes(data);                    }                }            }        }        /// summary        /// 向上遍历,更改父节点状态        /// 注意这里的父节点不是属性而是字段        /// 采用字段的原因是因为不想让父节点触发访问器而触发Setter        /// /summary        /// param nameCurrentNode/param        public void ChangedParentNodes(Device CurrentNode)        {            if (CurrentNode.ParentNode ! null)            {                bool? parentNodeState  true;                int selectedCount  0;  //被选中的个数                int noSelectedCount  0;    //不被选中的个数                foreach (var data in CurrentNode.ParentNode.ChildNodes)                {                    if (data.IsSelected  true)                    {                        selectedCount;                    }                    else if (data.IsSelected  false)                    {                        noSelectedCount;                    }                }                //如果全部被选中,则修改父节点为选中                if (selectedCount                      CurrentNode.ParentNode.ChildNodes.Count)                {                    parentNodeState  true;                }                //如果全部不被选中,则修改父节点为不被选中                else if (noSelectedCount                      CurrentNode.ParentNode.ChildNodes.Count)                {                    parentNodeState  false;                }                //否则标记父节点例如用实体矩形填满                else                {                    parentNodeState  null;                }                CurrentNode.parentNode.isSelected  parentNodeState;                CurrentNode.parentNode.NotifyPropertyChanged(IsSelected);                if (CurrentNode.ParentNode.ParentNode ! null)                {                    ChangedParentNodes(CurrentNode.parentNode);                }            }        }        public void NotifyPropertyChanged(string name)        {            if(PropertyChanged!null)            PropertyChanged(this,new PropertyChangedEventArgs(name));        }        public event PropertyChangedEventHandler PropertyChanged;    }    View具体实现代码  View Code CheckBox IsChecked{Binding IsSelected,ModeTwoWay} Margin2 VerticalAlignmentCenter/    这里只需要把实体的IsSelected属性Bingding到View上Mode是双向的就可以了具体的逻辑有实体内部做处理这样更能体现出View中代码的干净而且更能让View和ViewModel耦合性降到最低。实现三态树的时候有一个小技巧让代码避开了无限递归的问题这里采用属性如IsSelected属性有setter和gettter访问器当我们向上、下遍历的时候改变的是数据中的字段isSelected这样就不会触发了属性的setter。这也是数据驱动的一个优点之一。  4.总结       WPF的主要思想是用数据驱动来代替事件驱动。当数据发生变化的时候才做出一些相应的处理。这样的好处就是使得代码逻辑更加清晰。可以让数据发生变化通过属性访问器来控制相应的逻辑变化其实也是数据变化最后通知View。这样简化了逻辑处理而且减少了逻辑混乱的局面。有利于降低View和ViewModel(或后台具体实现代码)之间的耦合度也就是说有利于把强依赖关系转为弱依赖甚至没依赖关系。    5.附加源码点击下载       转载于:https://www.cnblogs.com/smlAnt/archive/2011/08/09/2130334.html
http://www.pierceye.com/news/406160/

相关文章:

  • wordpress显示icp备案号手机关键词排名优化
  • 网站建设与管理属于什么部门自助建站 知乎
  • 成都网站开发哪个好常州建网站
  • 陕西住房与城乡建设厅网站从化市营销型网站建设
  • 如何在网站上做推广自己做网站的图片
  • 珠海模板网站建设wordpress 底部工具栏
  • 网站建设的业务流程图招聘网站上找在家做
  • 网站设计的工具盱眙在仕德伟做网站的有几家
  • 建设一个网站要花多少时间临沂网站网站建设
  • 南宁网站推广经理做动漫网站如何应用数据绑定
  • 眼镜东莞网站建设兰州公司做网站
  • 改成 响应式 网站重庆微信企业网站
  • 用微信怎么做商城网站微信官网下载安装
  • 汽车网站建设方案预算md风格的wordpress主题
  • 免费外贸网站模板dede 网站栏目管理
  • 做网站有包括哪些东西站长素材网
  • 淘宝做促销的网站网站开发报价清单
  • 备案查询网站网站建设中可能遇到的问题
  • 怎么注册网站的步骤快速建站官网
  • 网站怎么做口碑wordpress淘宝客知乎
  • 响应式网站建设信息网站建设宽带
  • ps如何做网站超级链接微信公众平台运营中心电话
  • 网站建设怎么估算费用和报价h5特效网站欣赏
  • 东软集团建设网站娱乐网站排行榜
  • 石家庄网站建站米拓建站官网怎么用不了
  • 推广seo网站的公司金华网站建设公司排名
  • 阿里巴巴网站工作流程网站建设 教学设计
  • 电子商务网站建设的方法怎样用织梦做音乐网站
  • 临夏州住房和城乡建设局网站出词
  • 企业网站的综合要求最新领导班子7人名单