1. 因为需要对某一个项目的数据文件(xml类型)的文件进行编辑,手动输入十分不变,并且之后需要数据校正的功能,所以对DevExpress控件进行的半生不熟的应用。<br /><首先放一下界面照片>--之后有个问题就是删除的控件资源仍然在程序designer.cs里面,不小心把系统提示给关了<br />主窗体是mdicontainer,里面有splitContainerControl,将TreeList窗体置入panel1中<br />![image.png](https://cdn.nlark.com/yuque/0/2020/png/493122/1583668235504-e5ea5012-4dfd-4ad4-bf57-b49c0b19fd91.png#align=left&display=inline&height=310&name=image.png&originHeight=620&originWidth=1295&size=85718&status=done&style=none&width=647.5)<br />TreeForm<br />![image.png](https://cdn.nlark.com/yuque/0/2020/png/493122/1583668411162-a60d650f-272e-4cd9-8654-a26dcc7f3716.png#align=left&display=inline&height=349&name=image.png&originHeight=698&originWidth=915&size=42534&status=done&style=none&width=457.5)<br />两个窗体一个是ribbon类型的就是菜单栏文件、站场图、等对应不同的工具栏。但是container窗体只有一个,之后不知道怎么解决里面窗体的layout情况,之后填坑。<br />1.主窗体里主要写
    1. public partial class MainView : DevExpress.XtraBars.Ribbon.RibbonForm
    2. {
    3. public TreeForm treeForm;//这块主要写一个全局的TreeForm窗体释放之后可以重新实例化,不知道有没有问题
    4. public MainView()
    5. {
    6. InitializeComponent();
    7. if (!mvvmContext1.IsDesignMode)
    8. InitializeBindings();
    9. SkinHelper.InitSkinGallery(skinRibbonGalleryBarItem1, true);//这一部分主要是皮肤控件
    10. //显示MDI窗体
    11. this.IsMdiContainer = true;
    12. showTreeForm();
    13. }
    14. public void showTreeForm()//显示TreeForm窗体
    15. {
    16. treeForm = new TreeForm();
    17. treeForm.MdiParent = this;
    18. treeForm.TopLevel = false;
    19. treeForm.Dock = DockStyle.Fill;
    20. this.splitContainerControl1.Panel1.Controls.Add(treeForm);
    21. treeForm.Show();
    22. }
    23. void InitializeBindings()//所以需要在工具箱里找到mvvmContext置于窗体
    24. {
    25. var fluent = mvvmContext1.OfType<MainViewModel>();
    26. }
    27. }

    强烈建议添加皮肤因为 除了皮肤很多以外,还有很多很骚气的皮肤噢
    image.png

    康康多好看~~
    image.png

    还有万圣节特供款蛤蛤蛤
    image.png

    2.而在子窗体中则需要定义一个他的MdiParent窗体

    1. public partial class TreeForm : DevExpress.XtraEditors.XtraForm
    2. {
    3. public static MainView parentForm = new MainView();//因为打开一次TreeForm,主窗体关闭了才会释放mainview
    4. public TreeForm()
    5. {
    6. InitializeComponent();
    7. parentForm = (MainView)this.MdiParent;
    8. this.TopLevel = false;
    9. this.Dock = DockStyle.Fill;
    10. }
    11. private void TreeForm_Load(object sender, EventArgs e)
    12. {
    13. try
    14. {
    15. this.Dock = DockStyle.Fill;
    16. MainView parentForm = (MainView)this.MdiParent;//这句是设置主窗体
    17. }
    18. catch (Exception ex)
    19. {
    20. MessageBox.Show(ex.ToString());
    21. }
    22. }
    23. }

    3.接下来就是点击主窗体调用xml中的绑定xml文件至TreeList事件
    就是对象treeForm的showTree方法-第29行,需要提供文件列表即字符串数组,注意是完整路径

    1. private void btnOpenFile_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
    2. {
    3. if(!HaveOpened(this,"TreeForm"))
    4. {
    5. OpenChildForm(treeForm);
    6. showTreeForm();
    7. OpenXmlTree();
    8. }
    9. else
    10. {
    11. OpenChildForm(treeForm);
    12. treeForm.Activate();
    13. showTreeForm();
    14. OpenXmlTree();
    15. }
    16. }
    17. private void OpenXmlTree()
    18. {
    19. OpenFileDialog o = new OpenFileDialog();
    20. o.InitialDirectory = Application.StartupPath;
    21. o.Title = "打开文件";
    22. o.Multiselect = false;
    23. o.RestoreDirectory = true;
    24. o.Filter = "Xml文件(*.xml)|*.xml";
    25. o.Multiselect = true;
    26. if (o.ShowDialog() == DialogResult.OK)
    27. {
    28. string[] xmlFile = o.FileNames;
    29. treeForm.ShowTree(xmlFile);
    30. }
    31. }
    32. //查看窗口是否已经被打开或存在
    33. private bool HaveOpened(XtraForm MdiParentForm, string MdiChildFormType)
    34. {
    35. bool bReturn = false;
    36. for (int i = 0; i < MdiParentForm.MdiChildren.Length; i++)
    37. {
    38. if (MdiParentForm.MdiChildren[i].GetType().Name == MdiChildFormType)
    39. {
    40. MdiParentForm.MdiChildren[i].BringToFront();
    41. bReturn = true;
    42. break;
    43. }
    44. }
    45. return bReturn;
    46. }
    47. //MDI窗体不重复打开同一类型子窗体
    48. public void OpenChildForm(XtraForm formChild)
    49. {
    50. formChild.Name = formChild.GetType().FullName;
    51. bool isOpened = false;
    52. foreach (XtraForm form in this.MdiChildren)
    53. {//如果要显示的子窗体已经在子窗体的子窗体数组中,就把新建的多余的销毁
    54. if (formChild.GetType().ToString() == form.GetType().ToString())
    55. {
    56. form.Activate();
    57. formChild.Dispose();
    58. isOpened = true;
    59. break;
    60. }
    61. }
    62. if (!isOpened)
    63. {
    64. formChild.MdiParent = this;
    65. formChild.Show();
    66. }
    67. }

    4.之后就是TreeList中的一系列方法
    首先是定义一些全局变量,list类型的,模型的DataTable,主窗体文件集合待转换成的DataTable集合,主窗体提供的xml文件的文件路径
    public List ModelDataTables = new List(3);
    public List fileDataTables = new List();
    public List xmlModelsFilePaths = new List(3);//xml文件模型路径

    由于TreeForm中的TreeList需要时可编辑的,所以在构造函数中写
    此处出现了个大大的问题第12.15行
    <构造函数主要完成了:>
    1)构造主窗体还有他在主窗体中的dock
    2)得到已经在根目录中定义好的三个主要文件xml模型,GetFile得到文件路径,
    3)treeList高亮SearchControl—搜索框中的文本,但是不能利用treelist中的enabledFiltering设置为true,即把高亮的文本匹配置前

    1. public TreeForm()
    2. {
    3. InitializeComponent();
    4. parentForm = (MainView)this.MdiParent;
    5. this.TopLevel = false;
    6. this.Dock = DockStyle.Fill;
    7. //
    8. this.treeList2.OptionsBehavior.Editable = false;//treelist不可编辑
    9. GetFile();
    10. GetXmlModels();//得到模型文件的DataTable和树;
    11. //
    12. this.repositoryItemSearchControl1.Client = this.treeList2;
    13. //this.treeList2.OptionsBehavior.EnableFiltering = true;//有错误,不能自动过滤出最后的节点
    14. //原因好像是因为在treelist初始有树的情况下可以使用过滤,绑定数据源的情况下不能使用
    15. this.treeList2.OptionsFilter.FilterMode = FilterMode.Smart;
    16. //this.treeList2.FilterNode += treeList2_FilterNode;
    17. }
    18. private void GetFile()//集合模型文件的相对路径
    19. {
    20. string filepath = Application.StartupPath + "\\example\\xmlModels";
    21. xmlModelsFilePaths.Add(filepath + "\\TrackGeoInfo.xml");//轨道地理信息文件index=0
    22. xmlModelsFilePaths.Add(filepath + "\\MachineDatas.xml");//应用数据文件index=1
    23. xmlModelsFilePaths.Add(filepath + "\\IndexFile.xml");//区域索引文件index=2
    24. }
    25. private void GetXmlModels()//转换模型文件的DataTables模型
    26. {
    27. foreach (string s in xmlModelsFilePaths)
    28. {
    29. ModelDataTables.Add(XmlFileToTable(s));
    30. }
    31. }

    即添加主窗体传过来的文件路径
    showPage—即treelist展示xml文件

    1. #region MDI父窗体调用的函数
    2. //MDI父窗体打开页面时显示第一个文件树模型的操作
    3. public void ShowTree(string[] xmlFiles)
    4. {
    5. pageCount += xmlFiles.Length;//总页数增加
    6. foreach (string s in xmlFiles)
    7. {
    8. GetFilePages(s);
    9. }
    10. showPage(1);//显示第一份文件的xml树模型
    11. }
    12. #endregion

    <读取的xml文件首先转换成为DataTable,然后绑定Treelist的DataSource为DataTable导致了后面的很多问题>
    首先绑定数据源需要先设置TreeList的一些属性
    image.png
    点击RunDesigner,首先设置好TreeList中的Column这样之后才能绑定xml文件转成的DataTable
    image.png

    ParentID是斜的主要是因为设置了此column的visible为false不可见,<父级编号>是此列的Tag
    image.png

    注意设置Name和FiledName保持一致,因为Dev的TreeList和Winform的TreeView不太一样,有FiledName和KeyFieldName

    image.png
    想要忽略注释文本即xml文件中的需要这样写
    //读取时忽略注释信息
    XmlReaderSettings settings = new XmlReaderSettings();
    settings.IgnoreComments = true;
    XmlReader reader = XmlReader.Create(xmlFile, settings);
    xmlDoc.Load(reader);

    这些主要是设置节点名称、属性、和值
    dr[“MenuName”] = Node.Name.ToString();
    dr[“Tag”] = GetNodeAttributes(xmlnode);
    dr[“value”] = GetText(xmlnode);

    利用XmlFileToTable()就能够得到某一个xml文件的DataTable了

    1. #region 读xml文件转化生成树结构
    2. //需要提供xml文件的文件名称--存在问题DOM方式是否可取
    3. private DataTable XmlFileToTable(string xmlFile)
    4. {
    5. string fileName = xmlFile.Substring(xmlFile.LastIndexOf('\\') + 1, xmlFile.LastIndexOf('.') - xmlFile.LastIndexOf('\\') - 1);
    6. DataTable dt = new DataTable(fileName);
    7. dt.Columns.Add("ID");
    8. dt.Columns.Add("ParentID");
    9. dt.Columns.Add("MenuName");
    10. dt.Columns.Add("Tag");
    11. dt.Columns.Add("value");
    12. XmlDocument xmlDoc = new XmlDocument();
    13. //读取时忽略注释信息
    14. XmlReaderSettings settings = new XmlReaderSettings();
    15. settings.IgnoreComments = true;
    16. XmlReader reader = XmlReader.Create(xmlFile, settings);
    17. xmlDoc.Load(reader);
    18. ///
    19. XmlNode rootnode = xmlDoc.DocumentElement;
    20. DataRow dr = dt.NewRow();
    21. int Id = 1;
    22. dr["ID"] = Id++;
    23. dr["ParentID"] = 0;
    24. dr["MenuName"] = rootnode.Name.ToString();
    25. dr["Tag"] = GetNodeAttributes(rootnode);
    26. dr["value"] = GetText(rootnode);
    27. dt.Rows.Add(dr);
    28. if (rootnode.HasChildNodes)
    29. {
    30. XmlNodeList xmlnodelist = rootnode.ChildNodes;
    31. foreach (XmlNode xmlnode in xmlnodelist)
    32. {
    33. dr = dt.NewRow();
    34. dr["ID"] = Id++;
    35. dr["ParentID"] = 1;
    36. dr["MenuName"] = xmlnode.Name.ToString();
    37. dr["Tag"] = GetNodeAttributes(xmlnode);
    38. dr["value"] = GetText(xmlnode);
    39. dt.Rows.Add(dr);
    40. if (xmlnode.HasChildNodes)
    41. {
    42. int j = 1;
    43. XmlNodeList nodelist = xmlnode.ChildNodes;
    44. foreach (XmlNode node in nodelist)
    45. {
    46. int pId = Id;
    47. dr = dt.NewRow();
    48. dr["ID"] = Id++;
    49. dr["ParentID"] = pId - j;
    50. dr["MenuName"] = node.Name.ToString();
    51. dr["Tag"] = GetNodeAttributes(node);
    52. dr["value"] = GetText(node);//node.Value.ToString();
    53. dt.Rows.Add(dr);
    54. j++;
    55. if (node.HasChildNodes)
    56. {
    57. int i = 1;
    58. XmlNodeList list = node.ChildNodes;
    59. foreach (XmlNode Node in list)
    60. {
    61. if (Node.NodeType == XmlNodeType.Text)
    62. {
    63. continue;
    64. }
    65. else
    66. {
    67. int ppId = Id;
    68. dr = dt.NewRow();
    69. dr["ID"] = Id++;
    70. dr["ParentID"] = ppId - i;
    71. dr["MenuName"] = Node.Name.ToString();
    72. dr["Tag"] = GetNodeAttributes(xmlnode);
    73. dr["value"] = GetText(xmlnode);
    74. dt.Rows.Add(dr);
    75. i++;
    76. j++;
    77. }
    78. }
    79. }
    80. else
    81. {
    82. continue;
    83. }
    84. }
    85. }
    86. else
    87. {
    88. continue;
    89. }
    90. }
    91. }
    92. reader.Close();
    93. return dt;
    94. }
    95. //得到此节点的属性值,因为DOM方式属性节点即此节点的属性,和文本节点和注释节点不一样
    96. private string GetNodeAttributes(XmlNode node)
    97. {
    98. string result = null;
    99. if(node.Attributes!=null)
    100. {
    101. foreach(XmlAttribute x in node.Attributes)
    102. {
    103. result += x.Name.ToString() + "=" + x.Value.ToString()+" ";
    104. }
    105. }
    106. else
    107. {}
    108. return result;
    109. }
    110. private string GetText(XmlNode node)//得到节点内的值
    111. {
    112. string result = null;
    113. string nodename = node.Name.ToString();
    114. if (node.HasChildNodes&&node.ChildNodes.Count==1)
    115. {
    116. if (node.InnerText != null)
    117. result = node.InnerText.ToString();
    118. }
    119. return result;
    120. }
    121. //
    122. private DataTable GetCurrentDataTable()
    123. {
    124. string text = this.Text;
    125. DataTable temp = new DataTable();
    126. foreach(DataTable dt in fileDataTables)
    127. {
    128. if(text==dt.TableName)
    129. {
    130. temp = dt;
    131. temp.TableName = text;
    132. break;
    133. }
    134. }
    135. return temp;
    136. }
    137. #endregion

    <分页操作—转换好的DataTable需要显示在TreeList中,并且不是一个单独的文件,所以可以进行分页>
    此处有问题——由于showPage中主要是针对的主窗体的文件,并没有针对xmlmodel的文件,所以主要重载了一个showpage方法
    showpage方法主要实现了绑定数据源即超出页码限制datanavigator的按钮无效。
    由于DataNavigator的Button_Click调用了showEvent,保证了点击不同的pageindex,显示不同的showpage

    image.png

    1. #region 分页操作
    2. private void GetFilePages(string xmlFile)//得到多个文件的DataTables集合于fileDataTables
    3. {
    4. XmlDocument doc = new XmlDocument();
    5. doc.Load(xmlFile);
    6. XmlNode rootnode = doc.DocumentElement;
    7. fileDataTables.Add(XmlFileToTable(xmlFile));
    8. }
    9. //显示某一页DataTable
    10. public int pageIndex = 1;
    11. public int pageCount = 0;//初始赋值为0;
    12. private void showPage(int pageindex)
    13. {
    14. try
    15. {
    16. dataNavigator1.Buttons.CustomButtons[0].Enabled = true;
    17. dataNavigator1.Buttons.CustomButtons[1].Enabled = true;
    18. dataNavigator1.Buttons.CustomButtons[2].Enabled = true;
    19. dataNavigator1.Buttons.CustomButtons[3].Enabled = true;
    20. DataTable dt = fileDataTables[pageindex - 1];
    21. if (pageIndex == 1 || pageIndex == 0)
    22. {
    23. dataNavigator1.Buttons.CustomButtons[0].Enabled = false;
    24. dataNavigator1.Buttons.CustomButtons[1].Enabled = false;
    25. }
    26. if (dt.Rows.Count == 0)
    27. {
    28. pageIndex = 0;
    29. }
    30. if (pageCount == pageIndex)
    31. {
    32. dataNavigator1.Buttons.CustomButtons[2].Enabled = false;
    33. dataNavigator1.Buttons.CustomButtons[3].Enabled = false;
    34. }
    35. this.treeList2.Nodes.Clear();
    36. this.treeList2.DataSource = fileDataTables[pageindex - 1];
    37. this.treeList2.ExpandAll();
    38. this.Text = fileDataTables[pageindex - 1].TableName;
    39. dataNavigator1.TextStringFormat = string.Format("第{0}页,共{1}页", pageindex, pageCount);
    40. message.Caption = string.Format("共有{0}个节点", fileDataTables[pageindex - 1].Rows.Count);
    41. }
    42. catch (Exception ex)
    43. {
    44. XtraMessageBox.Show(ex.ToString());
    45. }
    46. }
    47. private void showPage(DataTable dataTable)
    48. {
    49. this.treeList2.Nodes.Clear();
    50. this.treeList2.DataSource = dataTable;
    51. this.treeList2.ExpandAll();
    52. this.Text = dataTable.TableName;
    53. dataNavigator1.TextStringFormat = string.Format("第{0}页,共{1}页",1 , 1);
    54. message.Caption = string.Format("共有{0}个节点", dataTable.Rows.Count);
    55. }
    56. //点击进度条事件改变treelist中显示的树
    57. private void dataNavigator1_ButtonClick(object sender,NavigatorButtonClickEventArgs e)
    58. {
    59. ShowEvent(e.Button);
    60. }
    61. private void ShowEvent(NavigatorButtonBase button)
    62. {
    63. NavigatorCustomButton btn = (NavigatorCustomButton)button;
    64. string type = btn.Tag.ToString();
    65. if (type == "首页")
    66. {
    67. pageIndex = 1;//pageIndex改变
    68. }
    69. if (type == "下一页")
    70. {
    71. pageIndex++;
    72. }
    73. if (type == "末页")
    74. {
    75. pageIndex = pageCount;
    76. }
    77. if (type == "上一页")
    78. {
    79. pageIndex--;
    80. }
    81. showPage(pageIndex);
    82. }
    83. //跳转按钮的操作
    84. private void btn_GoToPage_Click(object sender, EventArgs e)
    85. {
    86. if (pageCount > 0 && Convert.ToInt32(txt_pageindex.Text) <= pageCount)
    87. {
    88. pageIndex = Convert.ToInt32(txt_pageindex.Text);
    89. showPage(pageIndex);
    90. }
    91. else
    92. {
    93. XtraMessageBox.Show("请保证输入页码有效");
    94. }
    95. }
    96. //转页文本框的快捷键操作
    97. private void txt_pageindex_KeyPress(object sender, KeyPressEventArgs e)
    98. {
    99. if (e.KeyChar != '\b')//这是允许输入退格键
    100. {
    101. int len = txt_pageindex.Text.Length;
    102. if (len < 1 && e.KeyChar == '0')
    103. {
    104. e.Handled = true;
    105. }
    106. else if ((e.KeyChar < '0') || (e.KeyChar > '9'))//这是允许输入0-9数字
    107. {
    108. e.Handled = true;
    109. }
    110. }
    111. }
    112. private void txt_pageindex_KeyDown(object sender, KeyEventArgs e)
    113. {
    114. if(e.KeyData==Keys.Enter)
    115. {
    116. btn_GoToPage_Click(sender, e);
    117. }
    118. }
    119. #endregion

    <过滤数据事件—>
    构造函数中写首先定义searchControl的client必须设置为TreeList2
    this.repositoryItemSearchControl1.Client = this.treeList2;
    //this.treeList2.OptionsBehavior.EnableFiltering = true;//有错误,不能自动过滤出最后的节点
    //原因好像是因为在treelist初始有树的情况下可以使用过滤,绑定数据源的情况下不能使用
    this.treeList2.OptionsFilter.FilterMode = FilterMode.Smart;
    //this.treeList2.FilterNode += treeList2_FilterNode;

    以下是TreeList的过滤节点事件

    1. private void treeList2_FilterNode(object sender, FilterNodeEventArgs e)
    2. {
    3. if (treeList2.DataSource == null) return;
    4. string NodeText = e.Node.GetDisplayText("MenuName");
    5. if (string.IsNullOrWhiteSpace(NodeText)) return;
    6. bool IsVisible = NodeText.ToUpper().IndexOf(searchControl.EditValue.ToString().ToUpper()) >= 0;
    7. if (IsVisible)
    8. {
    9. TreeListNode Node = e.Node.ParentNode;
    10. while (Node != null)
    11. {
    12. if (!Node.Visible)
    13. {
    14. Node.Visible = true;
    15. Node = Node.ParentNode;
    16. }
    17. else
    18. break;
    19. }
    20. }
    21. e.Node.Visible = IsVisible;
    22. e.Handled = true;
    23. }

    <连带—父节点选中则子节点选中,每个子节点选中则父节点选中>

    1. //点击节点操作,出现复选框
    2. private void NodeEdit_ItemClick(object sender, ItemClickEventArgs e)
    3. {
    4. this.treeList2.OptionsBehavior.Editable = true;
    5. this.treeList2.OptionsView.ShowCheckBoxes = true;//出现复选框
    6. this.treeList2.OptionsBehavior.AllowIndeterminateCheckState = true;//允许一部分子节点选中
    7. }
    8. //节点选中前的事件
    9. private void treeList2_BeforeCheckNode(object sender, DevExpress.XtraTreeList.CheckNodeEventArgs e)
    10. {
    11. if (e.PrevState == CheckState.Checked)
    12. { e.State = CheckState.Unchecked; }
    13. else
    14. { e.State = CheckState.Checked; }
    15. }
    16. //节点选中后事件
    17. private void treeList2_AfterCheckNode(object sender, DevExpress.XtraTreeList.NodeEventArgs e)
    18. {
    19. SetCheckedChildNodes(e.Node, e.Node.CheckState);
    20. SetCheckedParentNodes(e.Node, e.Node.CheckState);
    21. //MessageBox.Show(e.Node.GetDisplayText("MenuName"));
    22. //this.treeList2.Selection.Add(e.Node);
    23. //AddCheckNodes(e.Node);
    24. //chooseNodes.Add(e.Node);
    25. }
    26. //此节点选中则所有子节点选中即子节点的子节点也选中.
    27. private void SetCheckedChildNodes(TreeListNode node, CheckState check)
    28. {
    29. for (int i = 0; i < node.Nodes.Count; i++)
    30. {
    31. node.Nodes[i].CheckState = check;
    32. SetCheckedChildNodes(node.Nodes[i], check);
    33. }
    34. }
    35. //遍历所有子节点都选中则父节点选中
    36. private void SetCheckedParentNodes(TreeListNode node, CheckState check)
    37. {
    38. if (node.ParentNode != null)//选中节点有父节点
    39. {
    40. bool IsSelected = false;
    41. CheckState state;
    42. for (int i = 0; i < node.ParentNode.Nodes.Count; i++)
    43. {
    44. state = (CheckState)node.ParentNode.Nodes[i].CheckState;//每个同胞节点的选中状态
    45. if (!check.Equals(state))//同胞节点状态不同则拒绝,退出
    46. {
    47. IsSelected = !IsSelected;
    48. break;
    49. }
    50. }
    51. if (IsSelected)//b为true即子节点并没有全部选中,此时父节点的状态为不确定状态
    52. {
    53. node.ParentNode.CheckState = CheckState.Indeterminate;
    54. }
    55. else
    56. {
    57. node.ParentNode.CheckState = check;
    58. }
    59. SetCheckedParentNodes(node.ParentNode, check);
    60. }
    61. }

    <弹出菜单操作>—-鼠标点击事件,需要工具箱的popupMenu,右击出现菜单按钮
    编辑时候需要点击customize
    image.png

    image.png

    1. //右键弹出菜单
    2. private void treeList2_MouseDown(object sender, MouseEventArgs e)
    3. {
    4. TreeList tree = sender as TreeList;
    5. if (e.Button == MouseButtons.Right
    6. && ModifierKeys == Keys.None
    7. && treeList2.State == TreeListState.Regular)
    8. {
    9. Point p = new Point(Cursor.Position.X, Cursor.Position.Y);
    10. TreeListHitInfo hitinfo = tree.CalcHitInfo(e.Location);
    11. if (hitinfo.HitInfoType == DevExpress.XtraTreeList.HitInfoType.Cell)
    12. {
    13. tree.SetFocusedNode(hitinfo.Node);
    14. }
    15. if (tree.FocusedNode != null)
    16. {
    17. popupMenu1.ShowPopup(p);
    18. }
    19. }
    20. }

    一些元数据(数据的数据)解析
    可以得到
    Point p = new Point(Cursor.Position.X, Cursor.Position.Y);//这一句得到光标的X,Y坐标
    TreeListHitInfo hitinfo = tree.CalcHitInfo(e.Location);//这一句得到光标下的TreeList下坐落某个元素(cell/column/row等等)

    1. TreeListHitInfo-------Gets the column located under the test point.
    2. 方法public TreeListHitInfo CalcHitInfo(Point pt);
    3. // 摘要:
    4. // Returns information about the Tree List's elements which are located at the specified
    5. // point.
    6. //
    7. // 参数:
    8. // pt:
    9. // A System.Drawing.Point structure which specifies test point coordinates relative
    10. // to the Tree List's top-left corner.
    11. //
    12. // 返回结果:
    13. // A DevExpress.XtraTreeList.TreeListHitInfo object which contains information about
    14. // the Tree List's elements located at the test point.
    15. 方法SetFocusNode(TreeListNode node)
    16. // 摘要:
    17. // Sets focus to a specific node within the current DevExpress.XtraTreeList.TreeList
    18. // control.
    19. //
    20. // 参数:
    21. // node:
    22. // The node to set focus on.
    23. //
    24. // 返回结果:
    25. // The index of the focused node among visible nodes.
    26. public virtual int SetFocusedNode(TreeListNode node);