using DevExpress.Data;
using DevExpress.XtraTreeList;
using DevExpress.XtraTreeList.Nodes;
using Gs.DevApp.Entity;
using Gs.DevApp.ToolBox;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Data;
using System.Drawing;
using System.Windows.Forms;
namespace Gs.DevApp.DevFrm.Sys
{
///
/// 看板目录管理 - 树形结构维护界面(用户控件)
///
public partial class SimpleKanBan : DevExpress.XtraEditors.XtraUserControl
{
private string _webServiceName = "MesSimpleManager/";
public SimpleKanBan()
{
InitializeComponent();
// 工具栏事件绑定
toolBarMenu1.btnLoadClick += ToolBarMenu1_btnLoadClick;
toolBarMenu1.btnQueryClick += ToolBarMenu1_btnQueryClick;
// TreeList 行号显示
tlMenu.IndicatorWidth = 50;
tlMenu.CustomDrawNodeIndicator += (s, ee) =>
{
if (ee.IsNodeIndicator)
{
var index = ee.Node.TreeList.GetVisibleIndexByNode(ee.Node);
ee.Info.DisplayText = (index + 1).ToString();
}
};
// 初始化加载数据
getPageList();
// 右键菜单事件
tlMenu.MouseDown += TlMenu_MouseDown;
// 增加子项
toolStripMenuItemAdd.Click += (s, ee) =>
{
string strGuid = "";
string strUpGuid = "";
if (tlMenu.FocusedNode != null)
{
strUpGuid = tlMenu.FocusedNode.GetValue("id").ToString();
}
SimpleKanBanEdit frm = new SimpleKanBanEdit(strGuid, strUpGuid);
frm.UpdateParent += (s2, ee2) =>
{
getPageList();
TreeListNode node = tlMenu.FindNodeByKeyID(long.Parse(strUpGuid));
if (node != null)
{
node.Expanded = true;
tlMenu.MakeNodeVisible(node);
}
};
frm.ShowDialog();
};
// 增加主项(根节点)
toolStripMenuItemRoot.Click += (s, ee) =>
{
string strGuid = "";
string strUpGuid = "";
SimpleKanBanEdit frm = new SimpleKanBanEdit(strGuid, strUpGuid);
frm.UpdateParent += (s2, ee2) =>
{
getPageList();
};
frm.ShowDialog();
};
// 删除节点
toolStripMenuItemDel.Click += (s, ee) =>
{
if (tlMenu.FocusedNode != null)
{
string rowGuid = "";
string rowName = "";
rowGuid = tlMenu.FocusedNode.GetValue("id").ToString();
rowName = tlMenu.FocusedNode.GetValue("title").ToString();
if (string.IsNullOrEmpty(rowGuid))
{
MsgHelper.Warning("请先选择你要操作的行!");
return;
}
if (!MsgHelper.AskQuestion("你选择了【" + rowName + "】,确定删除吗?"))
return;
List lst = new List();
lst.Add(rowGuid);
try
{
string strJson = UtilityHelper.HttpPost("", _webServiceName + "DeleteModel", JsonConvert.SerializeObject(lst));
ReturnModel _rtn = UtilityHelper.ReturnToDynamic(strJson);
if (_rtn.rtnCode > 0)
{
tlMenu.DeleteNode(tlMenu.FocusedNode);
}
else
MsgHelper.ShowError("提示:" + _rtn.rtnMsg);
}
catch (Exception ex)
{
MsgHelper.ShowError("提示:" + ex.Message);
}
}
};
// 创建刷新菜单项
ToolStripMenuItem toolStripMenuItemRefresh = new ToolStripMenuItem();
toolStripMenuItemRefresh.Text = "刷新";
toolStripMenuItemRefresh.Click += ToolBarMenu1_btnLoadClick; // 直接调用已有刷新事件
// 添加到右键菜单,不清空原有 Items
cms1.Items.Add(toolStripMenuItemRefresh);
// 编辑节点
toolStripMenuItemEdt.Click += (s, ee) =>
{
string strGuid = "";
string strUpGuid = "";
if (tlMenu.FocusedNode != null)
{
strGuid = tlMenu.FocusedNode.GetValue("id").ToString();
var fidValue = tlMenu.FocusedNode.GetValue("parentId");
strUpGuid = fidValue != null ? fidValue.ToString() : "";
}
SimpleKanBanEdit frm = new SimpleKanBanEdit(strGuid, strUpGuid);
frm.UpdateParent += (s2, ee2) =>
{
getPageList();
TreeListNode node = tlMenu.FindNodeByKeyID(long.Parse(strGuid));
if (node != null)
{
node.Expanded = true;
tlMenu.MakeNodeVisible(node);
}
};
frm.ShowDialog();
};
}
///
/// 查询事件
///
private void ToolBarMenu1_btnQueryClick(object sender, EventArgs e)
{
MsgHelper.ShowInformation("该窗体不支持查询,若想更新页面,请点击 刷新");
}
///
/// 刷新事件
///
private void ToolBarMenu1_btnLoadClick(object sender, EventArgs e)
{
getPageList();
MsgHelper.ShowInformation("刷新成功!");
}
///
/// 右键弹出菜单
///
private void TlMenu_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
TreeListHitInfo hInfo = tlMenu.CalcHitInfo(new Point(e.X, e.Y));
TreeListNode node = hInfo.Node;
tlMenu.FocusedNode = node;
if (hInfo.HitInfoType == HitInfoType.Cell ||
hInfo.HitInfoType == HitInfoType.Row ||
hInfo.HitInfoType == HitInfoType.RowIndent ||
hInfo.HitInfoType == HitInfoType.RowIndicator)
{
if (node != null)
{
toolStripMenuItemAdd.Visible = true;
toolStripMenuItemEdt.Visible = true;
toolStripMenuItemDel.Visible = true;
toolStripMenuItemRoot.Visible = false;
cms1.Show(tlMenu, e.Location);
}
}
else
{
toolStripMenuItemAdd.Visible = false;
toolStripMenuItemEdt.Visible = false;
toolStripMenuItemDel.Visible = false;
toolStripMenuItemRoot.Visible = true;
cms1.Show(tlMenu, e.Location);
}
}
}
///
/// 加载数据列表 - 树形结构显示
///
private void getPageList()
{
var pgq = new PageQueryModel(1, 999999, "a.node_level", "asc", "", "");//sort_order
var json = JsonConvert.SerializeObject(pgq);
try
{
var strReturn = UtilityHelper.HttpPost("", _webServiceName + "GetListPage", json);
var dd = UtilityHelper.ReturnToTablePage(strReturn);
var dt = dd.rtnData.list; // 获取原始 DataTable
// 检测 parentId 是否存在且类型不对
if (dt.Columns.Contains("parentId") && dt.Columns["parentId"].DataType != typeof(long))
{
// 1. 创建一个新的 Int64 类型的临时列
DataColumn newCol = new DataColumn("parentId_Fixed", typeof(long));
dt.Columns.Add(newCol);
// 2. 遍历所有行,把 String 转成 Long
foreach (DataRow row in dt.Rows)
{
object oldVal = row["parentId"];
// 只有非空值才转换,空值保持 DBNull (即根节点)
if (oldVal != null && oldVal != DBNull.Value && !string.IsNullOrEmpty(oldVal.ToString()))
{
if (long.TryParse(oldVal.ToString(), out long val))
{
row["parentId_Fixed"] = val;
}
}
}
// 3. 移除旧的 String 列
dt.Columns.Remove("parentId");
// 4. 把新列改名为 parentId
newCol.ColumnName = "parentId";
}
tlMenu.BeginUpdate();
// 1. 绑定处理过的数据
tlMenu.DataSource = dt;
// 2. 绑定字段 (现在类型完全一致了)
tlMenu.KeyFieldName = "id";
tlMenu.ParentFieldName = "parentId";
// 设置根节点 (Int64 类型的列,空值就是 DBNull)
tlMenu.RootValue = DBNull.Value;
string sortColName = "sortOrder";
if (tlMenu.Columns[sortColName] != null)
{
tlMenu.ClearSorting();
tlMenu.Columns[sortColName].SortOrder = System.Windows.Forms.SortOrder.Ascending;
tlMenu.Columns[sortColName].SortIndex = 0;
}
tlMenu.ForceInitialize();
// 4. 调用展开逻辑
ApplyExpandState();
tlMenu.EndUpdate();
tlMenu.BestFitColumns();
}
catch (Exception ex)
{
tlMenu.EndUpdate();
MsgHelper.Warning("加载失败:" + ex.Message);
}
}
///
/// 根据 isExpanded (bool) 字段设置节点展开
///
private void ApplyExpandState()
{
// 1. 先全部折叠
tlMenu.CollapseAll();
// 2. 使用 DevExpress 高效迭代器遍历
tlMenu.NodesIterator.DoOperation(node =>
{
// 获取值 (注意:列名必须与 DataTable 中一致,通常是 "isExpanded")
object val = node.GetValue("isExpanded");
// 3. 判断并展开
if (val != null && val != DBNull.Value)
{
if ((bool)val)
{
node.Expanded = true;
}
}
});
}
///
/// 将动态数据转换为DataTable
///
private DataTable ConvertToDataTable(dynamic sourceData)
{
DataTable dt = new DataTable();
if (sourceData == null) return dt;
// 如果已经是DataTable,直接返回
if (sourceData is DataTable)
return sourceData as DataTable;
// 尝试从JSON数组转换
string jsonStr = JsonConvert.SerializeObject(sourceData);
dt = JsonConvert.DeserializeObject(jsonStr);
return dt;
}
///
/// 处理parentId字段,确保树形结构正确构建
/// 根节点(node_level=0 或 parentId为null/0)的parentId设为DBNull
///
private void ProcessParentIdForTreeStructure(DataTable dt)
{
if (dt == null || dt.Rows.Count == 0) return;
foreach (DataRow row in dt.Rows)
{
// 获取nodeLevel
int nodeLevel = 0;
if (dt.Columns.Contains("nodeLevel") && row["nodeLevel"] != DBNull.Value)
{
nodeLevel = Convert.ToInt32(row["nodeLevel"]);
}
// 获取parentId
object parentIdValue = null;
if (dt.Columns.Contains("parentId"))
{
parentIdValue = row["parentId"];
}
// 如果是根节点(nodeLevel=0 或 parentId为null/0/空),将parentId设为DBNull
bool isRootNode = nodeLevel == 0;
bool hasNoParent = parentIdValue == null ||
parentIdValue == DBNull.Value ||
string.IsNullOrEmpty(parentIdValue.ToString()) ||
parentIdValue.ToString() == "0";
if (isRootNode || hasNoParent)
{
row["parentId"] = DBNull.Value;
}
}
}
///
/// 展开第一级节点(根节点)
///
private void ExpandFirstLevelNodes()
{
foreach (TreeListNode node in tlMenu.Nodes)
{
node.Expanded = true;
}
}
}
}