场景
使用DevExpress的TreeList显示本磁盘下文件目录并在树节点上右键实现删除与添加文件。
效果
自定义右键效果
实现
首先在包含Treelist的窗体的load方法中对treelist进行初始化
Common.DataTreeListHelper.RefreshTreeData(this.treeList1, 2);
其中this.treeList1就是当前窗体的treelist对象
然后第二个参数是默认展开级别。
public static void RefreshTreeData(DevExpress.XtraTreeList.TreeList treeList, int expandToLevel) { string rootNodeId = Common.Global.AppConfig.TestDataDir; string rootNodeText = ICSharpCode.Core.StringParser.Parse(ResourceService.GetString("Pad_DataTree_RootNodeText")); //"全部实验数据"; string fieldName = "NodeText"; string keyFieldName = "Id"; string parentFieldName = "ParentId"; List<DataTreeNode> data = new List<DataTreeNode>(); data = DataTreeListHelper.ParseDir(Common.Global.AppConfig.TestDataDir, data); data.Add(new DataTreeNode() { Id = rootNodeId, ParentId = String.Empty, NodeText = rootNodeText, NodeType = DataTreeNodeTypes.Folder }); DataTreeListHelper.SetTreeListDataSource(treeList, data, fieldName, keyFieldName, parentFieldName); treeList.ExpandToLevel(expandToLevel); }
在上面方法中新建根节点,根节点的Id就是要显示的目录,在配置文件中读取。
根节点的显示文本就是显示“全部实验数据”,从配置文件中获取。
然后调用工具类将目录结构转换成带父子级关系的节点的list,然后再将根节点添加到list。
然后调用设置treeList数据源的方法。
在上面方法中存取节点信息的DataTreeNode
public class DataTreeNode { private string id; private string parentId; private string nodeText; private string createDate; private string fullPath; private string taskFile; private string barcode; private DataTreeNodeTypes nodeType = DataTreeNodeTypes.Folder; public string Id { get { return id; } set { id = value; } } public string ParentId { get { return parentId; } set { parentId = value; } } public string NodeText { get { return nodeText; } set { nodeText = value; } } public string CreateDate { get { return createDate; } set { createDate = value; } } public string FullPath { get { return fullPath; } set { fullPath = value; } } public string TaskFile { get { return taskFile; } set { taskFile = value; } } public string Barcode { get { return barcode; } set { barcode = value; } } public DataTreeNodeTypes NodeType { get { return nodeType; } set { nodeType = value; } } }
在上面方法中将目录结构转换为节点list的方法
public static List<DataTreeNode> ParseDir(string dataRootDir, List<DataTreeNode> data) { if (data == null) { data = new List<DataTreeNode>(); } if (!System.IO.Directory.Exists(dataRootDir)) { return data; } DataTreeNode node = null; System.IO.DirectoryInfo dir = new System.IO.DirectoryInfo(dataRootDir); System.IO.DirectoryInfo[] subDirs = dir.GetDirectories(); foreach(System.IO.DirectoryInfo subDir in subDirs) { node = new DataTreeNode(); node.Id = subDir.FullName; node.ParentId = dir.FullName; node.NodeText = subDir.Name; node.CreateDate = String.Format("{0:yyyy-MM-dd HH:mm:ss}", subDir.CreationTime); node.FullPath = subDir.FullName; node.TaskFile = String.Empty; //任务文件名 node.NodeType = DataTreeNodeTypes.Folder; data.Add(node); ParseDir(subDir.FullName, data); } System.IO.FileInfo[] subFiles = dir.GetFiles(); return data; }
通过递归将上面传递过来的目录下的结构构造成节点的list并返回。
通过解析实验目录的方法返回list后再调用刷新treelist节点的方法
SetTreeListDataSource
public static void SetTreeListDataSource(DevExpress.XtraTreeList.TreeList treeList, List<DataTreeNode> data, string fieldName, string keyFieldName, string parentFieldName) { #region 设置节点图标 System.Windows.Forms.ImageList imgList = new System.Windows.Forms.ImageList(); imgList.Images.AddRange(imgs); treeList.SelectImageList = imgList; //目录展开 treeList.AfterExpand -= treeList_AfterExpand; treeList.AfterExpand += treeList_AfterExpand; //目录折叠 treeList.AfterCollapse -= treeList_AfterCollapse; treeList.AfterCollapse += treeList_AfterCollapse; //数据节点单击,开启整行选中 treeList.MouseClick -= treeList_MouseClick; treeList.MouseClick += treeList_MouseClick; //数据节点双击选中 treeList.MouseDoubleClick -= treeList_MouseDoubleClick; treeList.MouseDoubleClick += treeList_MouseDoubleClick; //焦点离开事件 treeList.LostFocus -= treeList_LostFocus; treeList.LostFocus += treeList_LostFocus; #endregion #region 设置列头、节点指示器面板、表格线样式 treeList.OptionsView.ShowColumns = false; //隐藏列标头 treeList.OptionsView.ShowIndicator = false; //隐藏节点指示器面板 treeList.OptionsView.ShowHorzLines = false; //隐藏水平表格线 treeList.OptionsView.ShowVertLines = false; //隐藏垂直表格线 treeList.OptionsView.ShowIndentAsRowStyle = false; #endregion #region 初始禁用单元格选中,禁用整行选中 treeList.OptionsView.ShowFocusedFrame = true; //设置显示焦点框 treeList.OptionsSelection.EnableAppearanceFocusedCell = false; //禁用单元格选中 treeList.OptionsSelection.EnableAppearanceFocusedRow = false; //禁用正行选中 //treeList.Appearance.FocusedRow.BackColor = System.Drawing.Color.Red; //设置焦点行背景色 #endregion #region 设置TreeList的展开折叠按钮样式和树线样式 treeList.OptionsView.ShowButtons = true; //显示展开折叠按钮 treeList.LookAndFeel.UseDefaultLookAndFeel = false; //禁用默认外观与感觉 treeList.LookAndFeel.UseWindowsXPTheme = true; //使用WindowsXP主题 treeList.TreeLineStyle = DevExpress.XtraTreeList.LineStyle.Percent50; //设置树线的样式 #endregion #region 添加单列 DevExpress.XtraTreeList.Columns.TreeListColumn colNode = new DevExpress.XtraTreeList.Columns.TreeListColumn(); colNode.Name = String.Format("col{0}", fieldName); colNode.Caption = fieldName; colNode.FieldName = fieldName; colNode.VisibleIndex = 0; colNode.Visible = true; colNode.OptionsColumn.AllowEdit = false; //是否允许编辑 colNode.OptionsColumn.AllowMove = false; //是否允许移动 colNode.OptionsColumn.AllowMoveToCustomizationForm = false; //是否允许移动至自定义窗体 colNode.OptionsColumn.AllowSort = false; //是否允许排序 colNode.OptionsColumn.FixedWidth = false; //是否固定列宽 colNode.OptionsColumn.ReadOnly = true; //是否只读 colNode.OptionsColumn.ShowInCustomizationForm = true; //移除列后是否允许在自定义窗体中显示 treeList.Columns.Clear(); treeList.Columns.AddRange(new DevExpress.XtraTreeList.Columns.TreeListColumn[] { colNode }); #endregion #region 绑定数据源 treeList.DataSource = null; treeList.KeyFieldName = keyFieldName; treeList.ParentFieldName = parentFieldName; treeList.DataSource = data; treeList.RefreshDataSource(); #endregion #region 初始化图标 SetNodeImageIndex(treeList.Nodes.FirstOrDefault()); #endregion }
如果不考虑根据文件还是文件夹设置节点图标和绑定其他双击事件等。
直接关注鼠标单击事件的绑定和下面初始化样式的设置。
在单击鼠标节点绑定的方法中
private static void treeList_MouseClick(object sender, System.Windows.Forms.MouseEventArgs e) { DevExpress.XtraTreeList.TreeList treeList = sender as DevExpress.XtraTreeList.TreeList; if (treeList != null && treeList.Selection.Count == 1) { object idValue = null; string strIdValue = String.Empty; DataTreeNode nodeData = null; List<DataTreeNode> datasource = treeList.DataSource as List<DataTreeNode>; if (datasource != null) { idValue = treeList.Selection[0].GetValue("Id"); strIdValue = idValue.ToString(); nodeData = datasource.Where<DataTreeNode>(p => p.Id == strIdValue).FirstOrDefault<DataTreeNode>(); if (nodeData != null) { if (nodeData.NodeType == DataTreeNodeTypes.File) { treeList.OptionsSelection.EnableAppearanceFocusedRow = true; //启用整行选中 if (e.Button == System.Windows.Forms.MouseButtons.Right) { System.Windows.Forms.ContextMenu ctxMenu = new System.Windows.Forms.ContextMenu(); #region 右键弹出上下文菜单 - 删除数据文件 System.Windows.Forms.MenuItem mnuDelete = new System.Windows.Forms.MenuItem(); mnuDelete.Text = "删除"; mnuDelete.Click += delegate(object s, EventArgs ea) { DialogResult dialogResult = DevExpress.XtraEditors.XtraMessageBox.Show(String.Format("确定要删除此实验数据吗[{0}]?\r\n删 除后无法恢复!", nodeData.Id), "标题", System.Windows.Forms.MessageBoxButtons.YesNo, MessageBoxIcon.Question); if (dialogResult == DialogResult.Yes) { try { string fileName = String.Empty; #region 删除数据文件 fileName = String.Format("{0}{1}", nodeData.Id, Global.MAIN_EXT); if (System.IO.File.Exists(fileName)) { System.IO.File.Delete(fileName); } #endregion #region 删除对应的树节点 DevExpress.XtraTreeList.Nodes.TreeListNode selectedNode = treeList.FindNodeByKeyID(nodeData.Id); if (selectedNode != null) { selectedNode.ParentNode.Nodes.Remove(selectedNode); } #endregion treeList.OptionsSelection.EnableAppearanceFocusedRow = false; //禁用整行选中 } catch(Exception ex) { ICSharpCode.Core.LoggingService<DataTreeListHelper>.Error("删除实验数据异常:" + ex.Message, ex); DevExpress.XtraEditors.XtraMessageBox.Show("删除实验数据异常:" + ex.Message, "标题", MessageBoxButtons.OK, MessageBoxIcon.Error); } } }; ctxMenu.MenuItems.Add(mnuDelete); #endregion #region 右键弹出上下文菜单 - 重命名数据文件 System.Windows.Forms.MenuItem mnuReName = new System.Windows.Forms.MenuItem(); mnuReName.Text = "重命名"; mnuReName.Click += delegate(object s, EventArgs ea) { //获取当前文件名 string oldName = Path.GetFileNameWithoutExtension(strIdValue); Dialog.FrmReName frmReName = new FrmReName(oldName); frmReName.StartPosition = FormStartPosition.CenterScreen; DialogResult result = frmReName.ShowDialog(); if (result == DialogResult.OK) { //刷入框新设置的文件名 string newName = frmReName.FileName; //获取原来路径 string filePath = Path.GetDirectoryName(strIdValue); //使用原来路径加 + 新文件名 结合成新文件路径 string newFilePath = Path.Combine(filePath, newName); DialogResult dialogResult = DevExpress.XtraEditors.XtraMessageBox.Show(String.Format("确定要将实验数据[{0}]重命名为 [{1}]吗?", nodeData.Id, newName), "标题", System.Windows.Forms.MessageBoxButtons.YesNo, MessageBoxIcon.Question); if (dialogResult == DialogResult.Yes) { try { string fileName = String.Empty; string newFileName = String.Empty; #region 重命名主通道数据文件 fileName = String.Format("{0}{1}", nodeData.Id, Global.MAIN_EXT); newFileName = String.Format("{0}{1}", newFilePath, Global.MAIN_EXT); if (System.IO.File.Exists(fileName)) { FileInfo fi = new FileInfo(fileName); fi.MoveTo(newFileName); } #endregion //刷新树 Common.DataTreeListHelper.TriggerRefreshDataEvent(); XtraMessageBox.Show("重命名成功"); treeList.OptionsSelection.EnableAppearanceFocusedRow = false; //禁用整行选中 } catch (Exception ex) { ICSharpCode.Core.LoggingService<DataTreeListHelper>.Error("删除实验数据异常:" + ex.Message, ex); DevExpress.XtraEditors.XtraMessageBox.Show("删除实验数据异常:" + ex.Message, "标题", MessageBoxButtons.OK, MessageBoxIcon.Error); } } } }; ctxMenu.MenuItems.Add(mnuReName); #endregion #endregion ctxMenu.Show(treeList, new System.Drawing.Point(e.X, e.Y)); } return; } } } treeList.OptionsSelection.EnableAppearanceFocusedRow = false; //禁用整行选中 } }
其中在进行重命名时需要弹出一个窗体
具体实现参照:
Winform巧用窗体设计完成弹窗数值绑定-以重命名弹窗为例:
https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/103155532