/****************************** * 说明:自动搜索框文本框 * 创建人:龚宇超 * 创建日期:2018-03-15 * 修改人: * 修改日期: * 修改备注: * 版本:1.0.0.0 ******************************/ using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Linq; using System.Text; using DevExpress.XtraEditors; using System.Drawing; using DevExpress.XtraGrid.Views.Grid; using System.Windows.Forms; using System.Data; using DevExpress.XtraGrid.Columns; using Lskj.Business.Impl; using Lskj.Control.Model; using System.Threading; using Lskj.Util; using System.Text.RegularExpressions; using Lskj.Business; namespace Lskj.Control { public partial class AutoTreeLookUp : TextEdit { /// /// 是否处理过计算 /// private bool _Handed; /// /// 弹出框最大宽度 /// private int _maxPopupWidth = 800; private string _value; private AutoTreePopup _popup = null; /// /// 弹出框是否显示 /// /// true if this instance is show popup; otherwise, false. public bool IsShowPopup; /// /// 是否需要自动匹配列宽度 /// [Description("是否需要自动匹配列宽度")] public bool IsBestFitColumns = true; /// /// The minimum popup width /// [Description("弹出框最小宽度")] public int MinPopupWidth; /// /// The minimum popup height /// [Description("弹出框最小高度")] public int MinPopupHeight; /// /// The value field /// public string ValueField = string.Empty; /// /// The value member /// [Description("设置ValueMember")] public string ValueMember = string.Empty; /// /// The text field /// [Description("设置TextMember")] public string TextMember = string.Empty; /// /// The remark text /// [Description("设置备注")] public string RemarkField = "remark"; /// /// 数据源 /// public string SourceSQL = string.Empty; /// /// 带参数数据源sql /// public string sourceParamSql = string.Empty; public string SpeciesValue; /// /// 控件对象 /// public ControlModel Model; /// /// The contro object /// public MyControl ControlObj; /// /// 数据源(用于匹配数据) /// public DataTable DataSourceTable; /// /// 隐藏值 /// public string EditValue = string.Empty; /// /// 是否是多选值 /// public bool isMultiClick; /// /// 根节点是否可以选中 /// public bool isRootNode = true; /// /// 是否执行刷新 /// public bool isRefresh = false; /// /// 完整数据源(输入框为空时查询出来的数据源) /// public DataTable CompleteData; /// /// 多选时返回全部(多选时,不是根节点是否能被选中) /// public bool SelectAll=false; /// /// 隐藏值 /// /// The value. //public new string EditValue //{ // get // { // BaseUserControl control = null; // if (this.Model != null) control = ControlObj.FindControl(this.Model.FieldName); // if (this.Model != null && (this.Model.FieldType == ControlType.LabAutoCompleteText || this.Model.FieldType == ControlType.LabAutoCompleteTextParam)) // { // // 自动搜索框显示名称、自动搜索框显示名称带参数时,直接显示与保存值,此时值可以任意输入,无需匹配数据源. // if (this.DataSource != null && this.DataSource is DataTable) // { // DataTable table = this.DataSourceTable != null ? this.DataSourceTable : this.DataSource as DataTable; // DataRow rowItem = table.Select("1=1").FirstOrDefault(x => control.EditText == x[TextMember] + ""); // if (rowItem == null) // { // rowItem = (this.DataSource as DataTable).Select("1=1").FirstOrDefault(x => control.EditText == x[TextMember] + ""); // if (rowItem == null) // return ""; // } // } // } // if (this.Model != null && (this.Model.FieldType == ControlType.LabAutoCompleteValue || this.Model.FieldType == ControlType.LabAutoCompleteValueParam)) // { // // 存在名称并且没有value值则 // if (control != null && string.IsNullOrEmpty(_value) && !string.IsNullOrEmpty(control.EditText)) // { // if (this.DataSource != null && this.DataSource is DataTable) // { // DataTable table = this.DataSourceTable != null ? this.DataSourceTable : this.DataSource as DataTable; // DataRow rowItem = table.Select("1=1").FirstOrDefault(x => control.EditText == x[TextMember] + ""); // if (rowItem != null) // { // return rowItem[ValueMember] + ""; // } // else // { // rowItem = (this.DataSource as DataTable).Select("1=1").FirstOrDefault(x => control.EditText == x[TextMember] + ""); // if (rowItem != null) // { // return rowItem[ValueMember] + ""; // } // } // } // } // } // return control != null && string.IsNullOrEmpty(control.EditText) ? "" : _value; // } // set // { // if (this.Model != null && (this.Model.FieldType == ControlType.LabTreeLookText || this.Model.FieldType == ControlType.LabAutoCompleteTextParam)) // { // // 自动搜索框显示名称、自动搜索框显示名称带参数时,直接显示与保存值,此时值可以任意输入,无需匹配数据源. // this.Text = this._value = value; // } // else // { // if (this.DataSource != null && this.DataSource is DataTable) // { // DataTable table = this.DataSourceTable != null && this.DataSourceTable.Rows.Count > 0 && !SourceSQL.ToLower().StartsWith("exec") ? this.DataSourceTable : this.DataSource as DataTable; // DataRow rowItem = table.Select("1=1").FirstOrDefault(x => value == x[ValueMember] + ""); // if (rowItem != null) // { // this._value = rowItem[ValueMember] + ""; // this.Text = rowItem[TextMember] + ""; // this.SelectionStart = this.Text.Length; // } // else // { // rowItem = (this.DataSource as DataTable).Select("1=1").FirstOrDefault(x => value == x[ValueMember] + ""); // if (rowItem != null) // { // this._value = rowItem[ValueMember] + ""; // this.Text = rowItem[TextMember] + ""; // this.SelectionStart = this.Text.Length; // } // else // { // this._value = string.Empty; // this.Text = string.Empty; // } // } // } // else // { // this._value = string.Empty; // this.Text = string.Empty; // } // } // } //} /// /// 说明:设置控件值 /// 创建人:龚宇超 /// 创建日期:2017-08-08 /// 修改人: /// 修改日期: /// 修改备注: /// 版本:1.0 /// public new string EditText { get { return this.Text; } set { if (!string.IsNullOrEmpty(value) && _popup != null && _popup.DataSource != null) { string[] values = value.Trim(',').Split(','); string text = string.Empty; this.EditValue = string.Empty; foreach (string item in values) { DataRow rowItem = _popup.TreeViewExObj.DataSource.Rows.Cast().FirstOrDefault(x => x[ValueMember] + "" == item); DataRow rowItemText = _popup.TreeViewExObj.DataSource.Rows.Cast().FirstOrDefault(x => x[TextMember] + "" == item); if (rowItem != null) { text += rowItem[TextMember] + ","; this.EditValue += rowItem[ValueMember] + ","; } if (rowItemText != null) { text += rowItemText[TextMember] + ","; this.EditValue += rowItemText[ValueMember] + ","; } } this.EditValue = EditValue.Trim(','); this.Text = text.Trim(','); } else { this.EditValue = ""; this.Text = ""; } if (string.IsNullOrWhiteSpace(this.EditValue)&& string.IsNullOrWhiteSpace(this.Text)&& this.Popup.TreeViewExObj.TreeView.SelectedNode != null) { // 树型下拉框要清空选中节点,否则下次再选相同的节点就选不上 this.Popup.TreeViewExObj.TreeView.SelectedNode = null; } } } /// /// 设置数据源 /// /// The data source. public object DataSource { get { return this._popup != null ? this._popup.TreeViewExObj.DataSource : null; } set { if (value != null) { this._popup.TreeViewObj.CheckBoxes = isMultiClick; this._popup.TreeViewExObj.TreeNodeKeyField = ValueMember; this._popup.TreeViewExObj.TreeNodeTextField = TextMember; this._popup.TreeViewExObj.BindTreeView(value as DataTable); } } } /// /// 说明:隐藏弹出框 /// 创建人:龚宇超 /// 创建日期:2018-03-16 /// 修改人: /// 修改日期: /// 修改备注: /// 版本:1.0 /// public void HidePopup() { if (this.IsShowPopup) { this.IsShowPopup = false; this._popup.Hide(); } } /// /// 说明:显示弹出框 /// 创建人:龚宇超 /// 创建日期:2018-03-16 /// 修改人: /// 修改日期: /// 修改备注: /// 版本:1.0 /// public void ShowPopup() { if (!this.Properties.ReadOnly && this.Enabled && !this.IsShowPopup) { this.IsShowPopup = true; this._popup.Show(); } } /// /// 弹出框 /// /// The popup. [Description("自动搜索弹出框")] public AutoTreePopup Popup { get { return this._popup; } private set { _popup = value; } } /// /// 界面关闭时 /// public event EventHandler OnPopupClosed; public AutoTreeLookUp() { InitializePopup(); InitializeEvent(); this.Disposed += OnDisposed; } /// /// 说明:初始化事件 /// 创建人:龚宇超 /// 创建日期:2018-03-16 /// 修改人: /// 修改日期: /// 修改备注: /// 版本:1.0 /// private void InitializeEvent() { this.MouseDown += new MouseEventHandler(OnAutoGridLookUpGotFocus); this.LostFocus += new EventHandler(OnAutoGridLookUpLostFocus); this.KeyUp += new KeyEventHandler(OnAutoGridLookUpKeyUp); //禁用右键(右键中的粘贴,撤回等不会触发处理事件,如KeyUp等) ContextMenuStrip emptyMenu = new ContextMenuStrip(); this.Properties.ContextMenuStrip = emptyMenu; this._popup.TreeViewObj.LostFocus += new EventHandler(OnAutoGridLookUpPopupLostFocus); if (isMultiClick) this._popup.TreeViewExObj.OnGridViewEnter += new KeyEventHandler(OnPopupGridViewEnter); //if (!isMultiClick) this._popup.TreeViewExObj.OnTreeNodeMouseClick += new TreeNodeMouseClickEventHandler(OnPopupNodeMouseClick); if (!isMultiClick) this._popup.TreeViewExObj.TreeNodeSelectAfter += new TreeViewEventHandler(OnPopupNodeSelectAfter); } /// /// 说明:初始化弹出框 /// 创建人:龚宇超 /// 创建日期:2018-03-15 /// 修改人: /// 修改日期: /// 修改备注: /// 版本:1.0 /// private void InitializePopup() { this._popup = new AutoTreePopup(); this._popup.LookUp = this; this._popup.Hide(); } /// /// 说明:计算弹出控件位置 /// 创建人:龚宇超 /// 创建日期:2018-03-16 /// 修改人: /// 修改日期: /// 修改备注: /// 版本:1.0 /// private void CalcPopupLocation() { this._popup.Parent = this.GetParent(this.Parent); Form form = this._popup.Parent as Form; if (form != null) { int iTop = this.Top + this.Height; int iLeft = this.Left; System.Windows.Forms.Control ctr = this.Parent; while (ctr != form) { iTop += ctr.Top; iLeft += ctr.Left; ctr = ctr.Parent; } if (iTop + this.Height + this._popup.Height > ctr.Height) { if (iTop - this.Height > ctr.Height - iTop) { if (this._popup.Height > iTop - this.Height) { this._popup.Height = iTop - this.Height; iTop = 0; } else { iTop = iTop - this.Height - this._popup.Height; } } else { this._popup.Height = ctr.Height - iTop - 30; } } if (iLeft + this._popup.Width > ctr.Width) { if (iLeft + this.Width > ctr.Width - iLeft) { if (this._popup.Width > iLeft + this.Width) { this._popup.Width = iLeft + this.Width; iLeft = 0; } else iLeft = iLeft + this.Width - this._popup.Width; } else this._popup.Width = ctr.Width - iLeft - 30; } this._popup.Left = iLeft; this._popup.Top = iTop; } this._popup.BringToFront(); } /// /// 说明: /// 创建人:龚宇超 /// 创建日期:2018-03-21 /// 修改人: /// 修改日期: /// 修改备注: /// 版本:1.0 /// public void RefreshPopupDataSource(string searchText) { if (string.IsNullOrEmpty(SourceSQL)) { // 本地搜索 } else { bool result = !string.IsNullOrEmpty(searchText); if (result == isRefresh&& string.IsNullOrEmpty(searchText)) return;//连续2次搜索都是空值,就不执行 isRefresh = !string.IsNullOrEmpty(searchText); // 数据库搜索 string sqlValue = string.Format("select * from ({0}\r\n) temp where {1} like '%{3}%' or {2} like '%{3}%' or dbo.P_getpy({2}) like '%{3}%'", string.IsNullOrEmpty(sourceParamSql) ? SourceSQL : sourceParamSql, ValueField, TextMember, searchText); if (!string.IsNullOrWhiteSpace(searchText)&& SystemInfo.Instance.TreeNodeBoxSpecialDisplay) { sqlValue= string.Format(@"select * from ({0} ) t1 where ({1} like '%{3}%' or {2} like '%{3}%' or dbo.P_getpy({2}) like '%{3}%') and NOT EXISTS( SELECT 1 FROM ({0} ) t2 where t2.{1} LIKE t1.{1} + '%' AND t2.{1} <> t1.{1})", string.IsNullOrEmpty(sourceParamSql) ? SourceSQL : sourceParamSql, ValueField, TextMember, searchText); this.DataSource = MainImpl.GetDataTableResult(sqlValue); //DataTable dataTable = MainImpl.GetDataTableResult(sqlValue); //if (string.IsNullOrWhiteSpace(searchText)) //{ // this.CompleteData = dataTable; //} //if (this.CompleteData == null) //{ // this.CompleteData = MainImpl.GetDataTableResult(string.IsNullOrEmpty(sourceParamSql) ? SourceSQL : sourceParamSql); //} //DataTable dataTableNew = dataTable.Clone(); //foreach (DataRow item in dataTable.Rows) //{ // string node = item[ValueField] + ""; // if (this.CompleteData.Select(ValueField + " like '" + node + "%'").Length == 1) // { // dataTableNew.ImportRow(item); // } //} //this.DataSource = dataTableNew; } else { //if (SystemInfo.Instance.TreeNodeBoxSpecialDisplay) this.DataSource = dataTable; this.DataSource = MainImpl.GetDataTableResult(sqlValue); } } } /// /// 说明:获取顶层窗口 /// 创建人:龚宇超 /// 创建日期:2018-03-16 /// 修改人: /// 修改日期: /// 修改备注: /// 版本:1.0 /// /// Control. private Form GetParent(System.Windows.Forms.Control ctr) { if (ctr == null) return null; return ctr is Form ? ctr as Form : GetParent(ctr.Parent); } /// /// 说明:设置值 /// 创建人:龚宇超 /// 创建日期:2018-03-16 /// 修改人: /// 修改日期: /// 修改备注: /// 版本:1.0 /// public void SetValue() { string ids = ""; if (this.isMultiClick) { //ids = Model.TreeCheckModel.Equals("1") ? this._popup.TreeViewExObj.GetCheckValues(true) : this._popup.TreeViewExObj.GetCheckValues(); /*2025-05-13日改 TreeCheckModel是设置选择模式的,为1的情况下,选中父节点后会自动选中所有子节点。直接根据TreeCheckModel控制是否只选择根节点感觉有问题 并且GetCheckValues(true)和GetCheckValues()效果相同(GetCheckValues有个不带参数的方法,里面默认为ture) 工具中和bs里 132-135都是只能选末级,136-139可以全选 true返回全部,false只返回根节点 */ ids = this.SelectAll ? this._popup.TreeViewExObj.GetCheckValues(true) : this._popup.TreeViewExObj.GetCheckValues(false); } else { ids = this._popup.TreeViewExObj.GetSelectNodeValue(); } if (ids != null) { ids = ids.Replace("'", ""); this.EditText = ids; this.Focus(); } if (this.OnPopupClosed != null) this.OnPopupClosed(this, null); } /// /// 说明:值为空时弹出搜索界面 /// 创建人:龚宇超 /// 创建日期:2018-03-16 /// 修改人: /// 修改日期: /// 修改备注: /// 版本:1.0 /// /// The source of the event. /// The instance containing the event data. protected void OnAutoGridLookUpGotFocus(object sender, EventArgs e) { this.CalcPopupLocation(); // 带参数sql,处理 if (this.ControlObj != null && Regex.IsMatch(SourceSQL, ReplaceHelper.ReplaceParamKey)) { sourceParamSql = SourceSQL; // Step 1:替换SpeciesNo List condition = ReplaceHelper.GetParamFields(sourceParamSql); if (!string.IsNullOrEmpty(SpeciesValue)) { foreach (string item in condition) { string field = item.Replace("{", "").Replace("}", ""); if ("speciesno".Equals(field, StringComparison.OrdinalIgnoreCase)) { sourceParamSql = sourceParamSql.Replace(item, SpeciesValue); } } } // Step 2:替换SpeciesNo if (this.ControlObj.CurrentData != null && this.ControlObj.CurrentData.Table.Columns.Contains("SpeciesNo")) { foreach (string item in condition) { string field = item.Replace("{", "").Replace("}", ""); if ("speciesno".Equals(field, StringComparison.OrdinalIgnoreCase)) { sourceParamSql = sourceParamSql.Replace(item, this.ControlObj.CurrentData["SpeciesNo"] + ""); } } } sourceParamSql = ControlObj.ReplaceControlValue(sourceParamSql.Replace("#", "")); this._popup.TreeViewExObj.BindTreeView(MainImpl.GetDataTableResult(sourceParamSql)); } this.ShowPopup(); if (isRefresh) this.RefreshPopupDataSource(""); _popup.TreeViewExObj.UnCheckAllNodes();//取消勾选所有节点 if (!string.IsNullOrWhiteSpace(this.EditValue)) { string[] spilts = this.EditValue.Trim().Replace(", ", ",").TrimEnd(',').Split(','); for (int i = 0; i < spilts.Length; i++) { string keyValue = spilts[i].Trim(); TreeNode[] nodes = _popup.TreeViewObj.Nodes.Find(keyValue, true); if (nodes.Count() > 0) { if (nodes[0].Parent != null) nodes[0].Parent.Expand(); nodes[0].Checked = true; _popup.TreeViewObj.SelectedNode = nodes[0]; _popup.TreeViewExObj.tvMain_AfterCheck(_popup.TreeViewExObj, new TreeViewEventArgs(nodes[0], TreeViewAction.ByMouse)); } } //_popup.TreeViewObj.Focus();//给了焦点后就不能在文本框中做搜索或者删除操作了 } } /// /// 说明: /// 创建人:龚宇超 /// 创建日期:2018-03-15 /// 修改人: /// 修改日期: /// 修改备注: /// 版本:1.0 /// /// The source of the event. /// The instance containing the event data. protected void OnPopupGridViewEnter(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.Enter) { this.SetValue(); this.HidePopup(); } } /// /// 说明: /// 创建人:王一帆 /// 创建日期:2021-03-29 /// 修改人: /// 修改日期: /// 修改备注: /// 版本:1.0 /// /// The source of the event. /// The instance containing the event data. protected void OnPopupDoubleEnter(object sender, TreeNodeMouseClickEventArgs e) { if (e.Node != null && e.Node.Bounds.Contains(e.Location)) { if (e.Node.Nodes.Count > 0 && !this.isRootNode) { return; } this.EditText = e.Node.Name; this.Focus(); this.HidePopup(); } } /// /// 说明:鼠标回调 /// 创建人:龚宇超 /// 创建日期:2018-03-15 /// 修改人: /// 修改日期: /// 修改备注: /// 版本:1.0 /// /// The source of the event. /// The instance containing the event data. protected void OnPopupNodeMouseClick(object sender, TreeNodeMouseClickEventArgs e) { this.SetValue(); } /// /// 说明:选中回调 /// 创建人:龚宇超 /// 创建日期:2018-03-15 /// 修改人: /// 修改日期: /// 修改备注: /// 版本:1.0 /// /// The source of the event. /// The instance containing the event data. protected void OnPopupNodeSelectAfter(object sender, TreeViewEventArgs e) { this.SetValue(); } /// /// 说明:当前控件失去焦点关闭界面 /// 创建人:龚宇超 /// 创建日期:2018-03-16 /// 修改人: /// 修改日期: /// 修改备注: /// 版本:1.0 /// /// The source of the event. /// The instance containing the event data. protected void OnAutoGridLookUpLostFocus(object sender, EventArgs e) { if (this._popup.Visible && !this._popup.Focused && !this._popup.TreeViewObj.Focused && !this.Focused) { this.HidePopup(); } /*还是觉得该放到下面注释的位置 目前有一个节点名称为 abc 的,删除了bc后。 控件里只显示了a,但是选中节点依旧是abc, * 下次如果不切换节点的话,在单击这个相同的节点。控件上的显示值不会刷新(显示a,但隐藏值是正确的) */ if (isRootNode) return; //if (isRefresh) this.RefreshPopupDataSource(""); string text = string.Empty; string keyValue = this.EditValue + ""; if (!string.IsNullOrEmpty(keyValue)) { string[] values = keyValue.Trim(',').Split(','); foreach (string item in values) { DataRow rowItem = _popup.TreeViewExObj.DataSource.Rows.Cast().FirstOrDefault(x => x[ValueMember] + "" == item); if (rowItem != null) { text += rowItem[TextMember] + ","; } } } text = text.TrimEnd(','); if (!text.Equals(this.Text)) { this.EditText = this.Text; } //if (isRootNode) return; TreeNode[] nodes = _popup.TreeViewObj.Nodes.Find(this.EditValue + "", true); if (nodes.Length > 0 && nodes[0].Nodes.Count > 0) { this.EditText = string.Empty; } } /// /// 说明:弹出框失去焦点关闭界面 /// 创建人:龚宇超 /// 创建日期:2018-03-16 /// 修改人: /// 修改日期: /// 修改备注: /// 版本:1.0 /// /// The source of the event. /// The instance containing the event data. protected void OnAutoGridLookUpPopupLostFocus(object sender, EventArgs e) { if (this._popup.Visible && !this._popup.Focused && !this._popup.TreeViewObj.Focused && !this.Focused) { this.HidePopup(); } if (isRootNode) return; if (isRefresh) this.RefreshPopupDataSource(""); string text = string.Empty; string keyValue = this.EditValue + ""; if (!string.IsNullOrEmpty(keyValue)) { string[] values = keyValue.Trim(',').Split(','); foreach (string item in values) { DataRow rowItem = _popup.TreeViewExObj.DataSource.Rows.Cast().FirstOrDefault(x => x[ValueMember] + "" == item); if (rowItem != null) { text += rowItem[TextMember] + ","; } } } text = text.Trim(','); if (!text.Equals(this.Text)) { this.EditText = this.Text; } //if (isRootNode) return; TreeNode[] nodes = _popup.TreeViewObj.Nodes.Find(this.EditValue + "", true); if (nodes.Length > 0 && nodes[0].Nodes.Count > 0) { this.EditText = string.Empty; } } /// /// 说明:鼠标弹起时刷新数据 /// 创建人:龚宇超 /// 创建日期:2018-03-16 /// 修改人: /// 修改日期: /// 修改备注: /// 版本:1.0 /// /// The source of the event. /// The instance containing the event data. prot