using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using ryCommon;

namespace ryControls
{
    /// <summary>
    /// 树形控件，用于分类用
    /// </summary>
    public partial class CtlTreeView : TreeView
    {
        private NodeItem StringToNodeItem(string tag)
        {
            ryCommon.Storage mStor = new ryCommon.Storage(tag);
            mStor.SelectNodeBySet();
            NodeItem item = new NodeItem(mStor.GetAttrValue("keys"), mStor.GetAttrValue("pwd"), mStor.GetAttrValue("user"));
            return item;
        }
        private string NodeItemToString(object Tag)
        {
            if (Tag != null)
            {
                NodeItem item = (NodeItem)Tag;
                ryCommon.Storage mStor = new ryCommon.Storage();
                mStor.SelectNodeBySet();
                mStor.SetAttrValue("keys", item.Keys);
                mStor.SetAttrValue("pwd", item.Pwd);
                mStor.SetAttrValue("user", item.AuthUser);
                return mStor.XMLText;
            }
            return "";
        }
        XmlDocument xmlDoc = new XmlDocument();//定义一个XML文档对象
        private string m_FirstShowText = "所有数据";
        /// <summary>
        /// 显示在第一位的名称
        /// </summary>
        [Description("显示在第一位的名称")]
        public string T_FirstShowText
        {
            get { return m_FirstShowText; }
            set { m_FirstShowText = value; }
        }
        private bool m_ShowMenu = true;
        /// <summary>
        /// 是否显示菜单
        /// </summary>
        [Description("是否显示菜单")]
        public bool T_ShowMenu
        {
            get { return m_ShowMenu; }
            set { m_ShowMenu = value; }
        }
        /// <summary>
        /// 树形控件
        /// </summary>
        public CtlTreeView()
        {
            InitializeComponent();
            menuAddGroup.Click += new EventHandler(MenuAddGroup_Click);
            menuEditGroup.Click += new EventHandler(MenuEditGroup_Click);
            menuDelGroup.Click += new EventHandler(MenuDelGroup_Click);
            menuGoPreGroup.Click += new EventHandler(MenuGoPreGroup_Click);
            menuSetPwd.Click += new EventHandler(MenuSetPwd_Click);
            menuSetAuthUser.Click += new EventHandler(MenuSetAuthUser_Click);
            menuGoNextGroup.Click += new EventHandler(MenuGoNextGroup_Click);
            this.MouseClick += new MouseEventHandler(CtlTreeView_MouseClick);
            this.ContextMenuStrip = contextMenuStrip1;
            this.ItemDrag += new ItemDragEventHandler(CtlTreeView_ItemDrag);
            this.DragEnter += new DragEventHandler(CtlTreeView_DragEnter);
            this.DragDrop += new DragEventHandler(CtlTreeView_DragDrop);
            this.DragOver += new DragEventHandler(CtlTreeView_DragOver);
            this.AfterCheck += new TreeViewEventHandler(CtlTreeView_AfterCheck);
            this.HotTracking = true;
            this.HideSelection = false;
        }
        void MenuSetAuthUser_Click(object sender, EventArgs e)
        {
            TreeNode tn = this.SelectedNode;
            if (tn == null) { return; }
            if (tn.Parent == null) { return; }
            if (OnBeforeSetAuth != null)
            {
                bool Cancel = false;
                OnBeforeSetAuth(this, ref Cancel);
                if (Cancel) { return; }
            }
            TreeXML.FrmAuthUser frm = new TreeXML.FrmAuthUser();
            frm.txtAuthUser.Text = GetNodeItem(tn).AuthUser;
            frm.txtAuthUser.DoubleClick += new EventHandler(TxtAuthUser_DoubleClick);
            if (frm.ShowDialog(this) == DialogResult.OK)
            {
                SetNodeItemForUser(tn, frm.txtAuthUser.Text);
                OnDataChange?.Invoke(this, new EventArgs());
            }
        }
        void MenuSetPwd_Click(object sender, EventArgs e)
        {
            TreeNode tn = this.SelectedNode;
            if (tn == null) { return; }
            if (tn.Parent == null) { return; }
            if (OnBeforeSetPwd != null)
            {
                bool Cancel = false;
                OnBeforeSetPwd(this, ref Cancel);
                if (Cancel) { return; }
            }
            TreeXML.FrmChangePwd frm = new TreeXML.FrmChangePwd()
            {
                oldPwd = GetNodeItem(tn).Pwd
            };
            if (frm.ShowDialog(this) == DialogResult.OK)
            {
                SetNodeItem(tn, frm.NewPwd);
                OnDataChange?.Invoke(this, new EventArgs());
            }
        }
        private void TreeParentChecked(TreeNode node, bool state)
        {
            TreeNode tn = node;
            while (true)
            {
                tn = tn.Parent;
                if (tn == null)
                {
                    break;
                }
                else
                {
                    tn.Checked = state;
                }
            }
        }
        void CtlTreeView_AfterCheck(object sender, TreeViewEventArgs e)
        {
            if (this.CheckBoxes)
            {
                if (e.Node.Checked && e.Action == TreeViewAction.ByMouse)
                {
                    //ctlTreeView1.setChildNodeCheckedState(e.Node, true);
                    TreeParentChecked(e.Node, true);
                    this.SetChildNodeCheckedState(e.Node, true);
                }
                else if (!e.Node.Checked && e.Action == TreeViewAction.ByMouse)
                {
                    //ctlTreeView1.setChildNodeCheckedState(e.Node, true);
                    bool isChecked = false;
                    TreeNode tn = e.Node.Parent;
                    if (tn != null)
                    {
                        for (int i = 0; i < tn.Nodes.Count; i++)
                        {
                            if (tn.Nodes[i].Checked) { isChecked = true; break; }
                        }
                    }
                    if (!isChecked)
                    {
                        TreeParentChecked(e.Node, false);
                    }
                    this.SetChildNodeCheckedState(e.Node, false);
                }
            }
        }

        void CtlTreeView_DragOver(object sender, DragEventArgs e)
        {
        }
        /// <summary>
        /// 判断指定节点是否是目标节点的子节点
        /// </summary>
        /// <param name="parent"></param>
        /// <param name="child"></param>
        /// <param name="isIncludeMe"></param>
        /// <returns></returns>
        public bool IsChildNode(TreeNode parent, TreeNode child,bool isIncludeMe)
        {
            if (parent == child && isIncludeMe) { return true; }
            TreeNode tn=child.Parent;
            while (true)
            {
                if (tn == parent)
                {
                    return true;
                }
                else
                {
                    tn = tn.Parent;
                    if (tn == null)
                    {
                        break;
                    }
                }
            }
            return false;
        }
        void CtlTreeView_DragDrop(object sender, DragEventArgs e)
        {
            //获得拖放中的节点  
            TreeNode moveNode = (TreeNode)e.Data.GetData("System.Windows.Forms.TreeNode");
            //根据鼠标坐标确定要移动到的目标节点  
            Point pt;
            TreeNode targeNode;
            pt = ((TreeView)(sender)).PointToClient(new Point(e.X, e.Y));
            targeNode = this.GetNodeAt(pt);
            //如果目标节点无子节点则添加为同级节点,反之添加到下级节点的未端  
            TreeNode NewMoveNode = (TreeNode)moveNode.Clone();
            if (!IsChildNode(moveNode, targeNode, false) && moveNode != targeNode)
            {
                //if (targeNode.Nodes.Count == 0)
                //{
                //    targeNode.Parent.Nodes.Insert(targeNode.Index, NewMoveNode);
                //}
                //else
                //{
                OnBeforeDataChange?.Invoke(this, new EventArgs());
                targeNode.Nodes.Insert(targeNode.Nodes.Count, NewMoveNode);
                //}
                //移除拖放的节点  
                moveNode.Remove();
                //更新当前拖动的节点选择  
                this.SelectedNode = NewMoveNode;
                //展开目标节点,便于显示拖放效果  
                this.ExpandAll();
                OnDataChange?.Invoke(this, new EventArgs());
            }
        }

        void CtlTreeView_DragEnter(object sender, DragEventArgs e)
        {
            if (OnBeforeEditGroup != null)
            {
                bool Cancel = false;
                OnBeforeEditGroup(this, ref Cancel);
                if (Cancel) { return; }
            }
            if (e.Data.GetDataPresent("System.Windows.Forms.TreeNode"))
            {
                e.Effect = DragDropEffects.Move;
            }
            else
            {
                e.Effect = DragDropEffects.None;
            }
        }

        void CtlTreeView_ItemDrag(object sender, ItemDragEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                DoDragDrop(e.Item, DragDropEffects.Move);
            }
        }

        void TxtAuthUser_DoubleClick(object sender, EventArgs e)
        {
            TextBox ct = (TextBox)sender;
            string User = ct.Text;
            bool Cancel=false;
            OnAuthUserSelect?.Invoke(this,ref User,ref Cancel);
            if (!Cancel)
            {
                ((TextBox)sender).Text = User;
            }
        }
        /// <summary>
        /// 判断当前节点，当前用户是否有权限访问
        /// </summary>
        /// <param name="tn"></param>
        /// <param name="user"></param>
        /// <param name="pwd"></param>
        /// <returns></returns>
        public bool IsHaveAuth(TreeNode tn,string user,string pwd)
        {
            NodeItem ni = GetNodeItem(tn);
            if(ni.AuthUser=="" || (";"+ni.AuthUser+";").IndexOf(";"+user+";")>=0)
            {
                if(ni.Pwd=="" || ni.Pwd==pwd)
                {
                    return true;
                }
            }
            return false;
        }

        void CtlTreeView_MouseClick(object sender, MouseEventArgs e)
        {
            try
            {
                TreeView tv = sender as TreeView;
                TreeNode select = tv.GetNodeAt(e.Location);                
                if (select != null)
                {
                //如果选择节点不是null，就设置为你的“选取结点”                    
                tv.SelectedNode = select;
                }
            } 
            catch{}
        }
        /// <summary>
        /// 权限事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="User"></param>
        /// <param name="Cancel"></param>
        public delegate void AuthUserHandler(object sender, ref string User,ref bool Cancel);
        /// <summary>
        /// 选择权限用户时发生
        /// </summary>
        [Description("选择权限用户时发生")]
        public event AuthUserHandler OnAuthUserSelect;
        /// <summary>
        /// 数据变化时发生
        /// </summary>
        [Description("数据变化时发生")]
        public event EventHandler OnDataChange;
        /// <summary>
        /// 数据变化前发生
        /// </summary>
        [Description("数据变化前发生")]
        public event EventHandler OnBeforeDataChange;
        /// <summary>
        /// 操作事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="Cancel"></param>
        public delegate void OptHandler(object sender, ref bool Cancel);
        /// <summary>
        /// 在添加分组前发生
        /// </summary>
        [Description("在添加分组前发生")]
        public event OptHandler OnBeforeAddGroup;
        /// <summary>
        /// 在修改分组前发生
        /// </summary>
        [Description("在修改分组前发生")]
        public event OptHandler OnBeforeEditGroup;
        /// <summary>
        /// 在删除分组前发生
        /// </summary>
        [Description("在删除分组前发生")]
        public event OptHandler OnBeforeDelGroup;
        /// <summary>
        /// 在设置密码前发生
        /// </summary>
        [Description("在设置密码前发生")]
        public event OptHandler OnBeforeSetPwd;
        /// <summary>
        /// 在设置权限前发生
        /// </summary>
        [Description("在设置权限前发生")]
        public event OptHandler OnBeforeSetAuth;
        void MenuGoNextGroup_Click(object sender, EventArgs e)
        {
            if (null == this.SelectedNode)
            {
                return;
            }
            TreeNode node = this.SelectedNode;
            TreeNode nextNode = node.NextNode;
            if (null != nextNode)
            {
                TreeNode newNode = (TreeNode)node.Clone();
                OnBeforeDataChange?.Invoke(this, new EventArgs());
                if (null == node.Parent)
                {
                    this.Nodes.Insert(nextNode.Index + 1, newNode);
                }
                else
                {
                    node.Parent.Nodes.Insert(nextNode.Index + 1, newNode);
                }
                node.Remove();
                this.SelectedNode = newNode;
                OnDataChange?.Invoke(this, new EventArgs());
            }
        }

        void MenuGoPreGroup_Click(object sender, EventArgs e)
        {
            if (null == this.SelectedNode)
            {
                return;
            }
            TreeNode node = this.SelectedNode;
            TreeNode prevNode = node.PrevNode;
            if (null != prevNode)
            {
                TreeNode newNode = (TreeNode)node.Clone();
                OnBeforeDataChange?.Invoke(this, new EventArgs());
                if (null == node.Parent)
                {
                    this.Nodes.Insert(prevNode.Index, newNode);
                }
                else
                {
                    node.Parent.Nodes.Insert(prevNode.Index, newNode);
                }
                node.Remove();
                this.SelectedNode = newNode;
                OnDataChange?.Invoke(this, new EventArgs());
            }
        }

        void MenuDelGroup_Click(object sender, EventArgs e)
        {
            if (this.SelectedNode == null) { return; }
            if (this.SelectedNode.Parent == null) { return; }
            if (MessageBox.Show("是否真的要删除?一旦删除就不可恢复！\r\n备注：删除分组时，不会删除该分组包含的内容。", "提示", MessageBoxButtons.YesNo, MessageBoxIcon.Information) == DialogResult.No) { return; }
            if (OnBeforeDelGroup != null)
            {
                bool Cancel = false;
                OnBeforeDelGroup(this, ref Cancel);
                if (Cancel) { return; }
            }
            OnBeforeDataChange?.Invoke(this, new EventArgs());
            this.SelectedNode.Remove();
            OnDataChange?.Invoke(this, new EventArgs());
        }

        void MenuEditGroup_Click(object sender, EventArgs e)
        {
            if (OnBeforeEditGroup != null)
            {
                bool Cancel = false;
                OnBeforeEditGroup(this, ref Cancel);
                if (Cancel) { return; }
            }
            if (this.SelectedNode == null) { return; }
            if (this.SelectedNode.Parent == null) { return; }
            TreeXML.frmAddTree frm = new TreeXML.frmAddTree()
            {
                T_IsAdd = 0,
                imageList1 = this.ImageList,
                T_SelectText = this.SelectedNode.Text,
                T_SelectTag = GetNodeItem(this.SelectedNode).Keys,
                T_ImageIndex = this.SelectedNode.ImageIndex
            };
            if (frm.ShowDialog(this) == DialogResult.OK)
            {
                OnBeforeDataChange?.Invoke(this, new EventArgs());
                this.SelectedNode.Text = frm.T_SelectText;
                SetNodeItemForKeys(this.SelectedNode, frm.T_SelectTag);
                this.SelectedNode.ImageIndex = frm.T_ImageIndex;
                //this.SelectedNode.StateImageIndex = frm.T_ImageIndex;
                this.SelectedNode.SelectedImageIndex = frm.T_ImageIndex;
                OnDataChange?.Invoke(this, new EventArgs());
            }
        }

        void MenuAddGroup_Click(object sender, EventArgs e)
        {
            if (OnBeforeAddGroup != null)
            {
                bool Cancel = false;
                OnBeforeAddGroup(this, ref Cancel);
                if (Cancel) { return; }
            }
            if (this.SelectedNode == null) { return; }
            TreeXML.frmAddTree frm = new TreeXML.frmAddTree()
            {
                imageList1 = this.ImageList,
                T_IsAdd = 1
            };
            if (frm.ShowDialog(this) == DialogResult.OK)
            {
                OnBeforeDataChange?.Invoke(this, new EventArgs());
                TreeNode new_child = new TreeNode()
                {
                    Text = frm.T_SelectText
                };
                SetNodeItemForKeys(new_child, GetNewKey());
                new_child.ImageIndex = frm.T_ImageIndex;
                new_child.SelectedImageIndex = frm.T_ImageIndex;
                //new_child.StateImageIndex = frm.T_ImageIndex;
                this.SelectedNode.Nodes.Add(new_child);
                this.ExpandAll();
                OnDataChange?.Invoke(this, new EventArgs());
            }
        }
        /// <summary>
        /// 获取新的关键词分类
        /// </summary>
        /// <returns></returns>
        private string GetNewKey()
        {
            Dictionary<string, int> dict = new Dictionary<string, int>();
            DiGui(Nodes[0]);
            int i = 0;
            while(true)
            {
                if(!dict.ContainsKey("N"+i.ToString()))
                {
                    return "N" + i.ToString();
                }
                i++;
            }
            void DiGui(TreeNode tn)
            {
                //
                foreach (TreeNode tnSub in tn.Nodes)
                {
                    NodeItem item = GetNodeItem(tnSub);
                    if(!dict.ContainsKey(item.Keys))
                    { dict.Add(item.Keys, 1); }
                    DiGui(tnSub);
                }
            }
        }
        /// <summary>
        /// 根据id获取节点
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public XmlElement GetNodeInfoById(string id)
        {
            //根据指定路径获取节点
            XmlElement element = null;
            XmlNode xmlNode = xmlDoc.SelectSingleNode("root/list[@id='" + id + "']");
            element = (XmlElement)xmlNode;
            return element;
        }
        /// <summary>
        /// 根据节点获取节点信息
        /// </summary>
        /// <param name="tn"></param>
        /// <returns></returns>
        public NodeItem GetNodeItem(TreeNode tn)
        {
            if (tn.Tag != null && tn.Tag.ToString() != "") { return (NodeItem)tn.Tag; }
            else { tn.Tag= new NodeItem("", "", ""); return (NodeItem)tn.Tag; }
        }
        /// <summary>
        /// 设置节点信息
        /// </summary>
        /// <param name="tn"></param>
        /// <param name="ni"></param>
        public void SetNodeItem(TreeNode tn,NodeItem ni)
        {
            NodeItem item = GetNodeItem(tn);
            OnBeforeDataChange?.Invoke(this, new EventArgs());
            item = ni;
        }
        /// <summary>
        /// 设置节点关键词和密码
        /// </summary>
        /// <param name="tn"></param>
        /// <param name="Keys"></param>
        /// <param name="pwd"></param>
        public void SetNodeItem(TreeNode tn,string Keys,string pwd)
        {
            NodeItem item = GetNodeItem(tn);
            OnBeforeDataChange?.Invoke(this, new EventArgs());
            item.Keys = Keys;
            item.Pwd = pwd;
        }
        /// <summary>
        /// 设置节点密码
        /// </summary>
        /// <param name="tn"></param>
        /// <param name="pwd"></param>
        public void SetNodeItem(TreeNode tn,string pwd)
        {
            NodeItem item = GetNodeItem(tn);
            OnBeforeDataChange?.Invoke(this, new EventArgs());
            item.Pwd = pwd;
        }
        /// <summary>
        /// 设置节点关键词
        /// </summary>
        /// <param name="tn"></param>
        /// <param name="Keys"></param>
        public void SetNodeItemForKeys(TreeNode tn, string Keys)
        {
            NodeItem item = GetNodeItem(tn);
            OnBeforeDataChange?.Invoke(this, new EventArgs());
            item.Keys = Keys;
        }
        /// <summary>
        /// 设置节点用户
        /// </summary>
        /// <param name="tn"></param>
        /// <param name="User"></param>
        public void SetNodeItemForUser(TreeNode tn, string User)
        {
            NodeItem item = GetNodeItem(tn);
            OnBeforeDataChange?.Invoke(this, new EventArgs());
            item.AuthUser = User;
        }
        /// <summary>
        /// RecursionTreeControl:表示将XML文件的内容显示在TreeView控件中
        /// </summary>
        /// <param name="xmlNode">将要加载的XML文件中的节点元素</param>
        /// <param name="nodes">将要加载的XML文件中的节点集合</param>
        private void RecursionTreeControl(XmlNode xmlNode, TreeNodeCollection nodes)
        {
            foreach (XmlNode node in xmlNode.ChildNodes)//循环遍历当前元素的子元素集合
            {
                TreeNode new_child = new TreeNode();
                try
                {
                    new_child.Text = (node.Attributes["Value"].Value == "null" ? "" : node.Attributes["Value"].Value) ;
                    try
                    {
                        var ImageIndex= node.Attributes["ImageIndex"].Value.ToInt();
                        var ImageKey = node.Attributes["ImageKey"];
                        var ImageKey_Str = ImageKey==null?"": ImageKey.Value;                       
                        if (ImageKey_Str == "")
                        {
                            new_child.ImageIndex = ImageIndex;
                            new_child.SelectedImageIndex = new_child.ImageIndex;
                        }
                        else
                        {
                            if (ImageList != null && ImageList.Images.Keys.Contains(ImageKey_Str))
                            {
                                new_child.ImageKey = ImageKey_Str;
                                new_child.SelectedImageKey = new_child.ImageKey;
                            }
                            else {
                                new_child.ImageIndex = ImageIndex;
                                new_child.SelectedImageIndex = new_child.ImageIndex;
                            }
                        }
                        //new_child.StateImageIndex = new_child.ImageIndex;
                    }
                    catch { }
                    //
                    NodeItem item = StringToNodeItem(node.Attributes["Tag"].Value);
                    new_child.Tag = item;
                }
                catch
                {
                    new_child.Tag = null;
                }
                switch (node.HasChildNodes)//判断是否存在子节点如果有继续递归
                {
                    case true:
                        RecursionTreeControl(node, new_child.Nodes);
                        break;
                    case false: break;
                }
                nodes.Add(new_child);//写入
                
            }
        }
        /// <summary>
        /// 把XML文本载入到列表中
        /// </summary>
        /// <param name="XMLText"></param>
        public void LoadFromXMLText(string XMLText)
        {
            try
            {
                base.Nodes.Clear();
                xmlDoc.RemoveAll();
                xmlDoc.LoadXml(XMLText);//加载XML文件
                TreeNode node = base.Nodes.Add(m_FirstShowText);
                node.Tag = null;
                RecursionTreeControl(xmlDoc.DocumentElement, node.Nodes);//在TreeView控件中显示内容
                base.ExpandAll();//展开TreeView控件中的所有项
            }
            catch
            {
                xmlDoc.LoadXml("<root></root>");//加载XML文件
                base.Nodes.Add(m_FirstShowText).Tag="";
            }
            if(base.Nodes.Count>0)
            {
                SelectedNode = base.Nodes[0];
            }
        }
        /// <summary>
        /// 把XML文件载入到列表中
        /// </summary>
        /// <param name="Path"></param>
        public void LoadFromFile(string Path)
        {
            base.Nodes.Clear();
            xmlDoc.Load(Path);//加载XML文件
            RecursionTreeControl(xmlDoc.DocumentElement, base.Nodes.Add(m_FirstShowText).Nodes);//在TreeView控件中显示内容
            base.ExpandAll();//展开TreeView控件中的所有项
        }
        private void TransTreeSav(TreeNodeCollection nodes, XmlElement ParXmlnode)
        {
            XmlNode Xmlroot;
            XmlElement xmlnode;
            Xmlroot = xmlDoc.SelectSingleNode("root");
            foreach (TreeNode node in nodes)
            {
                xmlnode = xmlDoc.CreateElement("list");
                xmlnode.SetAttribute("Value", node.Text);
                xmlnode.SetAttribute("Tag", NodeItemToString(node.Tag));
                xmlnode.SetAttribute("ImageIndex", node.ImageIndex.ToString());
                xmlnode.SetAttribute("ImageKey", node.ImageKey);
                ParXmlnode.AppendChild(xmlnode);
                if (node.Nodes.Count > 0)
                {
                    TransTreeSav(node.Nodes, xmlnode);
                }
            }
        }
        /// <summary>
        /// 将列表保存为xml文本
        /// </summary>
        /// <returns></returns>
        public string SaveToXmlText()
        {
            xmlDoc = new XmlDocument();
            //-------遍历树的各个故障节点，同时添加节点至XML
            xmlDoc.LoadXml("<root></root>");
            XmlElement Xmlnode = xmlDoc.CreateElement("list");
            XmlNode Xmlroot = xmlDoc.SelectSingleNode("root");

            //------遍历原treeview控件，并生成相应的XML
            TransTreeSav(base.Nodes[0].Nodes, (XmlElement)Xmlroot);
            return xmlDoc.OuterXml;
        }
        /// <summary>
        /// 改变所有子节点的状态
        /// </summary>
        /// <param name="currNode"></param>
        /// <param name="state"></param>
        public void SetChildNodeCheckedState(TreeNode currNode, bool state)
        {
            TreeNodeCollection nodes = currNode.Nodes;
            if (nodes.Count > 0)
            foreach (TreeNode tn in nodes)
            {
                tn.Checked = state;
                SetChildNodeCheckedState(tn, state);
            }
        }
        /// <summary>
        /// 反选子节点
        /// </summary>
        /// <param name="currNode"></param>
        public void SetChildNodeInvertChecked(TreeNode currNode)
        {
            TreeNodeCollection nodes = currNode.Nodes;
            if (nodes.Count > 0)
                foreach (TreeNode tn in nodes)
                {
                    tn.Checked =!tn.Checked;
                    SetChildNodeInvertChecked(tn);
                }
        }
        private void SetKeyCheckedState(TreeNode currNode, bool state, string keys)
        {
            TreeNodeCollection nodes = currNode.Nodes;
            if (nodes.Count > 0)
                foreach (TreeNode tn in nodes)
                {
                    if (keys.IndexOf(FormatKeysInfo(GetNodeItem(tn).Keys)) >= 0)
                    {
                        tn.Checked = state;
                    }
                    SetKeyCheckedState(tn, state, keys);
                }
        }
        /// <summary>
        /// 根据关键词来选中列表
        /// </summary>
        /// <param name="sKey"></param>
        public void CheckedTreeByKey(string sKey)
        {
            for (int i = 0; i < Nodes.Count; i++)
            {
                SetKeyCheckedState(Nodes[i], true, sKey);
            }
        }
        /// <summary>
        /// 根据关键词来选中列表
        /// </summary>
        /// <param name="sKey"></param>
        public void SelectedTreeByKey(string sKey)
        {
            for (int i = 0; i < Nodes.Count; i++)
            {
                SetKeySelected(Nodes[i], true, sKey);
            }
        }
        private void SetKeySelected(TreeNode currNode, bool state, string keys)
        {
            TreeNodeCollection nodes = currNode.Nodes;
            if (nodes.Count > 0)
            foreach (TreeNode tn in nodes)
            {
                if (keys==FormatKeysInfo(GetNodeItem(tn).Keys))
                {
                    this.SelectedNode = tn;
                    break;
                }
                SetKeySelected(tn, state, keys);
            }
        }
        /// <summary>
        /// 格式化关键字(会去除重复项)，以便存入数据库
        /// </summary>
        /// <param name="KeyItems"></param>
        /// <returns></returns>
        public string FormatKeysInfo(string KeyItems)
        {
            string tmpKeyItems = GetNoSame(KeyItems);
            tmpKeyItems = tmpKeyItems.Replace(";;", ";");
            tmpKeyItems = tmpKeyItems.Replace("；", ";");
            if (tmpKeyItems == ";" || tmpKeyItems.Length < 1)
            {
                tmpKeyItems = "";
                return tmpKeyItems;
            }
            tmpKeyItems = ";" + tmpKeyItems.Trim(';') + ";";
            return tmpKeyItems;
        }
        /// <summary>
        /// 去除掉重复项
        /// </summary>
        /// <param name="sList"></param>
        /// <returns></returns>
        public string GetNoSame(string sList)
        {
            string[] item = sList.Split(";".ToCharArray());
            string tmpStr = "";
            for (int i = 0; i < item.Length; i++)
            {
                if (item[i] != "" && (";" + tmpStr + ";").IndexOf(item[i]) < 0)
                {
                    tmpStr += ";" + item[i];
                }
            }
            return tmpStr;
        }
        /// <summary>
        /// 获取当前选中项以及所有父项的关键词组合
        /// </summary>
        /// <returns></returns>
        public string GetKey()
        {
            if (SelectedNode == null) { return ""; }
            if (SelectedNode.Parent != null)
            {
                TreeNode item = SelectedNode;
                string sKeys = "";
                while (item.Parent != null)
                {
                    sKeys += ";" + GetNodeItem(item).Keys;
                    item = item.Parent;
                }
                return FormatKeysInfo(GetNoSame(sKeys));
            }
            return "";
        }
        /// <summary>
        /// 获取选中的
        /// </summary>
        /// <param name="key_text"></param>
        /// <param name="e"></param>
        /// <returns></returns>
        public string GetCheckedKey(string key_text,TreeViewEventArgs e)
        {
            if (e.Node.Checked)
            {
                string sKeys = key_text + ";" + GetNodeItem(e.Node).Keys;
                return FormatKeysInfo(sKeys);
            }
            else
            {
                string sKeys = ";" + key_text + ";";
                sKeys = FormatKeysInfo(sKeys);
                string myKey = GetNodeItem(e.Node).Keys;
                if (myKey != "")
                {
                    sKeys = sKeys.Replace(myKey, "");
                }
                return FormatKeysInfo(sKeys);
            }
        }
        private void ContextMenuStrip1_Opening(object sender, CancelEventArgs e)
        {
            if (!m_ShowMenu) { e.Cancel = true; }
            if (this.SelectedNode == null) { return; }
            menuAddGroup.Enabled=this.SelectedNode.Name != "nokeys";
            if (this.SelectedNode.Parent == null)
            {
                menuDelGroup.Enabled = false;
                menuEditGroup.Enabled = false;
                menuGoNextGroup.Enabled = false;
                menuGoPreGroup.Enabled = false;
            }
            else
            {
                menuDelGroup.Enabled = true;
                menuEditGroup.Enabled = true;
                menuGoNextGroup.Enabled = true;
                menuGoPreGroup.Enabled = true;
            }
        }
        
    }
}
