feat: 将主页左侧菜单迁移到 TreeList

This commit is contained in:
2026-08-10 14:55:10 +08:00
parent 000a69ce15
commit f92fd2f1cc
2 changed files with 219 additions and 114 deletions
+215 -113
View File
@@ -11,6 +11,9 @@ using DevExpress.LookAndFeel;
using DevExpress.XtraEditors;
using DevExpress.XtraTab;
using DevExpress.XtraTab.ViewInfo;
using DevExpress.XtraTreeList;
using DevExpress.XtraTreeList.Columns;
using DevExpress.XtraTreeList.Nodes;
using Lskj.Business;
using Lskj.Business.Impl;
using Lskj.Control;
@@ -129,12 +132,19 @@ namespace Lskj.Main.Control
/// 缓存分组控件
/// </summary>
private Dictionary<string, Panel> _groupItems = new Dictionary<string, Panel>();
private TreeView _leftGroupTreeView;
private ImageList _leftGroupTreeIcons;
private TreeList _leftGroupTreeView;
private TreeListNode _leftGroupHotNode;
private TreeListNode _leftGroupSelectedNode;
private ImageList _leftGroupTreeImageList;
private Panel _leftGroupSeparator;
private const string LeftGroupTreeNodeTypeMenu = "menu";
private const string LeftGroupTreeNodeTypeGroup = "group";
private const int GroupControlTopPadding = 8;
private static readonly Color LeftGroupTreeBackgroundColor = Color.FromArgb(39, 45, 81);
private static readonly Color LeftGroupTreeActiveColor = Color.FromArgb(52, 142, 216);
private static readonly Color LeftGroupTreeTextColor = Color.FromArgb(235, 255, 255, 255);
private static readonly Color LeftGroupTreeArrowColor = Color.FromArgb(173, 255, 255, 255);
/// <summary>
/// 缓存右上菜单控件
/// </summary>
@@ -741,32 +751,171 @@ namespace Lskj.Main.Control
return groupCaption.Length > 2 ? groupCaption.Remove(0, 2) : groupCaption;
}
private TreeView GetLeftGroupTreeView()
private TreeList GetLeftGroupTreeView()
{
if (_leftGroupTreeView != null) return _leftGroupTreeView;
_leftGroupTreeView = new TreeView
_leftGroupTreeView = new TreeList
{
Dock = DockStyle.Fill,
BorderStyle = BorderStyle.None,
BackColor = Color.FromArgb(250, 253, 255),
DrawMode = TreeViewDrawMode.Normal,
Font = new Font("微软雅黑", 10F),
ForeColor = Color.FromArgb(38, 73, 98),
HideSelection = false,
Indent = 20,
ImageList = GetLeftGroupTreeIcons(),
ItemHeight = 29,
LineColor = Color.FromArgb(198, 214, 226),
ShowLines = false,
ShowPlusMinus = false,
ShowRootLines = false
BorderStyle = DevExpress.XtraEditors.Controls.BorderStyles.NoBorder,
RowHeight = ScaleLeftGroupTreeMetric(44),
TreeLevelWidth = ScaleLeftGroupTreeMetric(18)
};
_leftGroupTreeView.NodeMouseClick += OnLeftGroupTreeViewNodeMouseClick;
TreeListColumn textColumn = new TreeListColumn
{
Caption = "功能导航",
FieldName = "nodetext",
Visible = true,
VisibleIndex = 0
};
textColumn.OptionsColumn.AllowEdit = false;
_leftGroupTreeView.Columns.Add(textColumn);
_leftGroupTreeView.OptionsBehavior.Editable = false;
_leftGroupTreeView.OptionsSelection.EnableAppearanceFocusedCell = false;
_leftGroupTreeView.OptionsSelection.EnableAppearanceFocusedRow = true;
_leftGroupTreeView.OptionsView.AutoWidth = true;
_leftGroupTreeView.OptionsView.ExpandButtonCentered = true;
_leftGroupTreeView.OptionsView.ShowButtons = false;
_leftGroupTreeView.OptionsView.ShowColumns = false;
_leftGroupTreeView.OptionsView.ShowFocusedFrame = false;
_leftGroupTreeView.OptionsView.ShowHorzLines = false;
_leftGroupTreeView.OptionsView.ShowIndentAsRowStyle = true;
_leftGroupTreeView.OptionsView.ShowIndicator = false;
_leftGroupTreeView.OptionsView.ShowVertLines = false;
_leftGroupTreeView.Appearance.Empty.BackColor = LeftGroupTreeBackgroundColor;
_leftGroupTreeView.Appearance.Empty.Options.UseBackColor = true;
_leftGroupTreeView.Appearance.Row.BackColor = LeftGroupTreeBackgroundColor;
_leftGroupTreeView.Appearance.Row.ForeColor = LeftGroupTreeTextColor;
_leftGroupTreeView.Appearance.Row.Font = new Font("微软雅黑", 10F);
_leftGroupTreeView.Appearance.Row.Options.UseBackColor = true;
_leftGroupTreeView.Appearance.Row.Options.UseForeColor = true;
_leftGroupTreeView.Appearance.Row.Options.UseFont = true;
_leftGroupTreeView.Appearance.FocusedRow.BackColor = LeftGroupTreeActiveColor;
_leftGroupTreeView.Appearance.FocusedRow.ForeColor = Color.White;
_leftGroupTreeView.Appearance.FocusedRow.Options.UseBackColor = true;
_leftGroupTreeView.Appearance.FocusedRow.Options.UseForeColor = true;
_leftGroupTreeView.Appearance.HideSelectionRow.BackColor = LeftGroupTreeActiveColor;
_leftGroupTreeView.Appearance.HideSelectionRow.ForeColor = Color.White;
_leftGroupTreeView.Appearance.HideSelectionRow.Options.UseBackColor = true;
_leftGroupTreeView.Appearance.HideSelectionRow.Options.UseForeColor = true;
_leftGroupTreeView.SelectImageList = GetLeftGroupTreeImageList();
_leftGroupTreeView.AfterCollapse += OnLeftGroupTreeListAfterExpandOrCollapse;
_leftGroupTreeView.AfterExpand += OnLeftGroupTreeListAfterExpandOrCollapse;
_leftGroupTreeView.MouseClick += OnLeftGroupTreeListMouseClick;
_leftGroupTreeView.MouseLeave += OnLeftGroupTreeListMouseLeave;
_leftGroupTreeView.MouseMove += OnLeftGroupTreeListMouseMove;
return _leftGroupTreeView;
}
private ImageList GetLeftGroupTreeImageList()
{
if (_leftGroupTreeImageList != null) return _leftGroupTreeImageList;
_leftGroupTreeImageList = new ImageList
{
ColorDepth = ColorDepth.Depth32Bit,
ImageSize = new Size(ScaleLeftGroupTreeMetric(14), ScaleLeftGroupTreeMetric(14)),
TransparentColor = Color.Transparent
};
_leftGroupTreeImageList.Images.Add(CreateLeftGroupTreeArrowImage(false, LeftGroupTreeArrowColor));
_leftGroupTreeImageList.Images.Add(CreateLeftGroupTreeArrowImage(true, LeftGroupTreeArrowColor));
_leftGroupTreeImageList.Images.Add(CreateLeftGroupTreeArrowImage(false, Color.White));
_leftGroupTreeImageList.Images.Add(CreateLeftGroupTreeArrowImage(true, Color.White));
return _leftGroupTreeImageList;
}
private Bitmap CreateLeftGroupTreeArrowImage(bool expanded, Color color)
{
Size imageSize = _leftGroupTreeImageList.ImageSize;
Bitmap bitmap = new Bitmap(imageSize.Width, imageSize.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
using (Graphics graphics = Graphics.FromImage(bitmap))
{
graphics.Clear(Color.Transparent);
graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
int centerX = imageSize.Width / 2;
int centerY = imageSize.Height / 2;
Point[] points;
if (expanded)
{
int width = ScaleLeftGroupTreeMetric(8);
int height = ScaleLeftGroupTreeMetric(6);
points = new[]
{
new Point(centerX - width / 2, centerY - height / 2),
new Point(centerX + width / 2, centerY - height / 2),
new Point(centerX, centerY + height / 2)
};
}
else
{
int width = ScaleLeftGroupTreeMetric(6);
int height = ScaleLeftGroupTreeMetric(8);
points = new[]
{
new Point(centerX - width / 2, centerY - height / 2),
new Point(centerX - width / 2, centerY + height / 2),
new Point(centerX + width / 2, centerY)
};
}
using (SolidBrush arrowBrush = new SolidBrush(color))
{
graphics.FillPolygon(arrowBrush, points);
}
}
return bitmap;
}
private int ScaleLeftGroupTreeMetric(int value)
{
float dpi = DpiX > 0 ? DpiX : 96F;
return Math.Max(1, Convert.ToInt32(value * dpi / 96F));
}
private void OnLeftGroupTreeListAfterExpandOrCollapse(object sender, NodeEventArgs e)
{
UpdateLeftGroupTreeNodeArrow(e == null ? null : e.Node);
}
private void UpdateLeftGroupTreeNodeArrow(TreeListNode node)
{
if (node == null || node.Level != 0) return;
node.ImageIndex = node.Expanded ? 1 : 0;
node.SelectImageIndex = node.Expanded ? 3 : 2;
}
private void OnLeftGroupTreeListMouseMove(object sender, MouseEventArgs e)
{
TreeList treeList = sender as TreeList;
if (treeList == null) return;
TreeListHitInfo hitInfo = treeList.CalcHitInfo(e.Location);
TreeListNode hotNode = hitInfo == null ? null : hitInfo.Node;
if (hotNode == _leftGroupHotNode) return;
_leftGroupHotNode = hotNode;
treeList.FocusedNode = _leftGroupHotNode ?? _leftGroupSelectedNode;
}
private void OnLeftGroupTreeListMouseLeave(object sender, EventArgs e)
{
TreeList treeList = sender as TreeList;
if (treeList == null) return;
_leftGroupHotNode = null;
if (_leftGroupSelectedNode != null)
{
treeList.FocusedNode = _leftGroupSelectedNode;
}
}
private Panel GetLeftGroupSeparator()
{
if (_leftGroupSeparator != null) return _leftGroupSeparator;
@@ -823,118 +972,71 @@ namespace Lskj.Main.Control
}
}
private ImageList GetLeftGroupTreeIcons()
{
if (_leftGroupTreeIcons != null) return _leftGroupTreeIcons;
_leftGroupTreeIcons = new ImageList();
_leftGroupTreeIcons.ColorDepth = ColorDepth.Depth32Bit;
_leftGroupTreeIcons.ImageSize = new Size(18, 18);
string iconPath = PubUtil.MainTreeviewImagePath;
if (Directory.Exists(iconPath))
{
string[] files = Directory.GetFiles(iconPath, "*.png").OrderBy(n => n).ToArray();
foreach (string file in files)
{
using (Image image = ImageHelper.ReadImage(file))
{
if (image != null)
{
_leftGroupTreeIcons.Images.Add(new Bitmap(image));
}
}
}
}
if (_leftGroupTreeIcons.Images.Count == 0)
{
_leftGroupTreeIcons.Images.Add(new Bitmap(18, 18));
}
return _leftGroupTreeIcons;
}
private void BindLeftGroupTreeView(DataTable treeTable, string defaultNode)
{
TreeView treeView = GetLeftGroupTreeView();
treeView.BeginUpdate();
treeView.Nodes.Clear();
Dictionary<string, TreeNode> nodeMap = new Dictionary<string, TreeNode>();
List<DataRow> rows = treeTable.Rows.Cast<DataRow>()
.OrderBy(n => Convert.ToInt32(n["sortno"]))
.ToList();
int iconCount = GetLeftGroupTreeIcons().Images.Count;
foreach (DataRow row in rows)
TreeList treeList = GetLeftGroupTreeView();
treeList.BeginUpdate();
try
{
TreeNode node = new TreeNode(row["nodetext"] + "");
int iconIndex = 0;
int.TryParse(row["iconindex"] + "", out iconIndex);
iconIndex = Math.Abs(iconIndex) % iconCount;
node.ImageIndex = iconIndex;
node.SelectedImageIndex = iconIndex;
node.Name = row["nodekey"] + "";
node.Tag = row;
nodeMap[node.Name] = node;
}
treeList.Nodes.Clear();
_leftGroupHotNode = null;
_leftGroupSelectedNode = null;
foreach (DataRow row in rows)
{
string nodeKey = row["nodekey"] + "";
string parentKey = row["parentkey"] + "";
TreeNode node = nodeMap[nodeKey];
if (!string.IsNullOrEmpty(parentKey) && nodeMap.ContainsKey(parentKey))
Dictionary<string, TreeListNode> nodeMap = new Dictionary<string, TreeListNode>();
List<DataRow> rows = treeTable.Rows.Cast<DataRow>()
.OrderBy(n => Convert.ToInt32(n["sortno"]))
.ToList();
foreach (DataRow row in rows)
{
nodeMap[parentKey].Nodes.Add(node);
string nodeKey = row["nodekey"] + "";
string parentKey = row["parentkey"] + "";
TreeListNode parentNode = !string.IsNullOrEmpty(parentKey) && nodeMap.ContainsKey(parentKey)
? nodeMap[parentKey]
: null;
TreeListNode node = treeList.AppendNode(new object[] { row["nodetext"] + "" }, parentNode);
node.Tag = row;
if (parentNode == null)
{
UpdateLeftGroupTreeNodeArrow(node);
}
else
{
node.ImageIndex = -1;
node.SelectImageIndex = -1;
}
nodeMap[nodeKey] = node;
}
else
treeList.CollapseAll();
if (!string.IsNullOrEmpty(defaultNode) && nodeMap.ContainsKey(defaultNode))
{
treeView.Nodes.Add(node);
_leftGroupSelectedNode = nodeMap[defaultNode];
treeList.FocusedNode = _leftGroupSelectedNode;
}
}
treeView.CollapseAll();
FocusLeftGroupTreeNode(defaultNode);
treeView.EndUpdate();
}
private void FocusLeftGroupTreeNode(string nodeKey)
{
if (_leftGroupTreeView == null || string.IsNullOrEmpty(nodeKey)) return;
TreeNode node = FindLeftGroupTreeNode(_leftGroupTreeView.Nodes, nodeKey);
if (node == null) return;
_leftGroupTreeView.SelectedNode = node;
}
private TreeNode FindLeftGroupTreeNode(TreeNodeCollection nodes, string nodeKey)
{
foreach (TreeNode node in nodes)
finally
{
if (node.Name.Equals(nodeKey)) return node;
TreeNode childNode = FindLeftGroupTreeNode(node.Nodes, nodeKey);
if (childNode != null) return childNode;
treeList.EndUpdate();
}
return null;
}
private void OnLeftGroupTreeViewNodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
private void OnLeftGroupTreeListMouseClick(object sender, MouseEventArgs e)
{
try
{
TreeView treeView = sender as TreeView;
if (treeView == null || e.Node == null || e.Button != MouseButtons.Left) return;
TreeList treeList = sender as TreeList;
if (treeList == null || e.Button != MouseButtons.Left) return;
treeView.SelectedNode = e.Node;
if (e.Node.Nodes.Count > 0)
TreeListHitInfo hitInfo = treeList.CalcHitInfo(e.Location);
if (hitInfo == null || hitInfo.Node == null) return;
_leftGroupSelectedNode = hitInfo.Node;
treeList.FocusedNode = _leftGroupSelectedNode;
if (hitInfo.Node.HasChildren && hitInfo.HitInfoType != HitInfoType.Button)
{
e.Node.Toggle();
hitInfo.Node.Expanded = !hitInfo.Node.Expanded;
}
OnLeftGroupTreeRowClick(e.Node.Tag as DataRow);
OnLeftGroupTreeRowClick(hitInfo.Node.Tag as DataRow);
}
catch (Exception ex)
{
@@ -950,11 +1052,11 @@ namespace Lskj.Main.Control
string expandNode = GetLeftGroupTreeDefaultNode(treeTable, defaultParentMenu);
this.pl_center_left.Controls.Clear();
this.pl_center_left.Padding = Padding.Empty;
this.pl_center_left.BackColor = Color.FromArgb(250, 253, 255);
this.pl_center_left.BackColor = LeftGroupTreeBackgroundColor;
this.pl_center_main.Padding = Padding.Empty;
this.pl_center_main.BackColor = Color.FromArgb(240, 240, 240);
SetLeftGroupSeparatorVisible(true);
TreeView treeView = GetLeftGroupTreeView();
TreeList treeView = GetLeftGroupTreeView();
this.pl_center_left.Controls.Add(treeView);
BindLeftGroupTreeView(treeTable, expandNode);
+3
View File
@@ -73,6 +73,9 @@
<Reference Include="DevExpress.XtraGrid.v15.2, Version=15.2.4.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
</Reference>
<Reference Include="DevExpress.XtraTreeList.v15.2, Version=15.2.4.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
</Reference>
<Reference Include="libzkfpcsharp, Version=1.0.0.1, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\引用DLL\libzkfpcsharp.dll</HintPath>