using NaiBa.Util.Extension; using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Drawing; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; using Work.Extension; namespace Work.UserComponents { public partial class UcComboBoxMutiSelect : ComboBox { //private bool _IsMultiSelect; //public bool IsMultiSelect { get => _IsMultiSelect; set => _IsMultiSelect = value; } string defaultText = "全部"; [Browsable(true), Description("默认文本"), Category("自定义分组")] public string DefaultText { get { return defaultText; } set { defaultText = value; this.Text = defaultText; this.Invalidate(); } } public List SelectItems { get { if (this.checkedListBox == null) return this.Items.Cast().ToList(); List lstObj = new List(); for (int i = 0; i < checkedListBox.Items.Count; i++) { if (checkedListBox.GetItemChecked(i)) { lstObj.Add(checkedListBox.Items[i]); } } return lstObj; } } Label lblX = null; CheckedListBox checkedListBox = null; public UcComboBoxMutiSelect() { SetStyle(ControlStyles.DoubleBuffer | ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true); UpdateStyles(); this.Text = DefaultText; this.DropDownWidth = 1; this.DropDownHeight = 1; this.DropDown += UcComboBoxMutiSelect_DropDown; this.DropDownClosed += UcComboBoxMutiSelect_DropDownClosed; Task.Run(() => { for (int i = 0; i < 50; i++) { System.Threading.Thread.Sleep(100); var parentForm = FindForm(); if (parentForm != null && parentForm.Visible == true) { Invoke(new Action(() => { UpdateClearLabel(); })); break; } } this.Move += UcComboBoxMutiSelect_Move; this.Resize += UcComboBoxMutiSelect_Resize; this.SizeChanged += UcComboBoxMutiSelect_SizeChanged; this.VisibleChanged += UcComboBoxMutiSelect_VisibleChanged; this.ParentChanged += UcComboBoxMutiSelect_ParentChanged; this.Disposed += UcComboBoxMutiSelect_Disposed; }); } private void UcComboBoxMutiSelect_Disposed(object sender, EventArgs e) { if (lblX != null) lblX.Dispose(); } private void UcComboBoxMutiSelect_ParentChanged(object sender, EventArgs e) { //lblX.Parent.Controls.Remove(lblX); //lblX.Dispose(); //lblX = null; if (this != null && !this.IsDisposed && this.Parent != null) { this.GetParentNotTable().Controls.Add(lblX); UpdateClearLabel(); } } private void UcComboBoxMutiSelect_VisibleChanged(object sender, EventArgs e) { if (lblX != null && lblX.Visible != this.Visible) lblX.Visible = this.Visible; } private void UcComboBoxMutiSelect_SizeChanged(object sender, EventArgs e) { UpdateClearLabel(); } private void UcComboBoxMutiSelect_Resize(object sender, EventArgs e) { UpdateClearLabel(); } private void UcComboBoxMutiSelect_Move(object sender, EventArgs e) { UpdateClearLabel(); } private void UpdateClearLabel() { if (lblX == null || lblX.Disposing || lblX.IsDisposed) { lblX = new Label(); lblX.Click += LblX_Click; //lblX.BorderStyle = BorderStyle.FixedSingle; lblX.Text = "×"; lblX.ForeColor = Color.FromArgb(63, 126, 255); lblX.BackColor = this.BackColor; lblX.AutoSize = false; //lblX.AutoSize = true; //lblX.Width = 17; lblX.Width = 15; lblX.Height = 19; lblX.SendToBack(); //Form form = this.FindForm(); //form.Controls.Add(lblX); var p = this.GetParentNotTable(); if (p != null) p.Controls.Add(lblX); } Point relativeLocation = this.GetRelativePosition(this.GetParentNotTable()); lblX.Location = new Point(relativeLocation.X + this.Width - 19 - lblX.Width, relativeLocation.Y + (this.Height - lblX.Height) / 2); lblX.Visible = this.Visible; lblX.BringToFront(); } private void LblX_Click(object sender, EventArgs e) { if (this.lblX.Text == "×") { this.lblX.Text = "↶"; this.Text = ""; } else { this.lblX.Text = "×"; this.Text = DefaultText; } } private void UcComboBoxMutiSelect_DropDownClosed(object sender, EventArgs e) { if (checkedListBox != null) { var parentForm = this.FindForm(); Point mousePosition = parentForm.PointToClient(Cursor.Position); Point relativeLocation = checkedListBox.GetRelativePosition(); if (mousePosition.X < relativeLocation.X || mousePosition.X > relativeLocation.X + checkedListBox.Width || mousePosition.Y < relativeLocation.Y || mousePosition.Y > relativeLocation.Y + checkedListBox.Height) { checkedListBox.Visible = false; } } } private void UcComboBoxMutiSelect_DropDown(object sender, EventArgs e) { var parentForm = this.FindForm(); if (checkedListBox == null) { checkedListBox = new CheckedListBox(); checkedListBox.Visible = false; checkedListBox.CheckOnClick = true; checkedListBox.ItemCheck += checkedListBox_ItemCheck; checkedListBox.MouseLeave += checkedListBox_MouseLeave; checkedListBox.MouseEnter += CheckedListBox_MouseEnter; checkedListBox.MouseMove += CheckedListBox_MouseMove; //checkedListBox.MouseUp += new MouseEventHandler(checkedListBox_MouseUp); parentForm.Controls.Add(checkedListBox); } string str1 = string.Join(",", this.Items.Cast().Select(o => o.ParseToString())); string str2 = string.Join(",", this.checkedListBox.Items.Cast().Select(o => o.ParseToString())); if (str1 != str2) { checkedListBox.Items.Clear(); if (Items.Count > 0) checkedListBox.ItemCheck -= checkedListBox_ItemCheck; foreach (var item in this.Items) { if (Items[Items.Count - 1] == item) checkedListBox.ItemCheck += checkedListBox_ItemCheck; checkedListBox.Items.Add(item.ParseToString(), true); } } // 防止一起设置每次都要重新拼接字符串 if (checkedListBox.Items.Count > 0) checkedListBox.ItemCheck -= checkedListBox_ItemCheck; for (int index = 0; index < checkedListBox.Items.Count; index++) { if (index == checkedListBox.Items.Count - 1) checkedListBox.ItemCheck += checkedListBox_ItemCheck; var item = checkedListBox.Items[index]; if (this.Text == DefaultText || this.Text.Split(new string[] { ";", ";", ",", "," }, StringSplitOptions.RemoveEmptyEntries).ToList().Contains(item.ParseToString())) checkedListBox.SetItemChecked(index, true); else checkedListBox.SetItemChecked(index, false); } // 计算宽度 int maxItemWidth = 0; for (int index = 0; index < checkedListBox.Items.Count; index++) { var wth = TextRenderer.MeasureText(checkedListBox.Items[index].ToString(), checkedListBox.Font).Width + 40; if (wth > maxItemWidth) maxItemWidth = wth; } checkedListBox.SendToBack(); checkedListBox.Visible = true; // 确定弹出列表框的大小和位置 //checkedListBox.Size = new Size(Math.Max(80, this.Width), Math.Min(300, checkedListBox.PreferredHeight)); checkedListBox.Size = new Size(Math.Max(this.Width, maxItemWidth), Math.Min(300, checkedListBox.PreferredHeight)); Point relativeLocation = this.GetRelativePosition(); if (parentForm.Height - relativeLocation.Y >= this.Height + checkedListBox.Size.Height + 20) relativeLocation = new Point(relativeLocation.X, relativeLocation.Y + this.Height); else relativeLocation = new Point(relativeLocation.X, relativeLocation.Y - checkedListBox.Size.Height); checkedListBox.Location = relativeLocation; checkedListBox.BringToFront(); //parentForm.ActiveControl = checkedListBox; //checkedListBox.Focus(); } private void CheckedListBox_MouseMove(object sender, MouseEventArgs e) { //this.DropDownClosed -= UcComboBoxMutiSelect_DropDownClosed; } private void CheckedListBox_MouseEnter(object sender, EventArgs e) { //this.DropDownClosed -= UcComboBoxMutiSelect_DropDownClosed; } private void checkedListBox_MouseLeave(object sender, EventArgs e) { ////this.DropDownClosed += UcComboBoxMutiSelect_DropDownClosed; ////统计选取的项目 //string str = ""; //for (int i = 0; i < checkedListBox.Items.Count; i++) //{ // if (checkedListBox.GetItemChecked(i)) // { // str += $"{checkedListBox.Items[i].ParseToString()};"; // } //} //this.Text = str; checkedListBox.Visible = false; this.OnDropDownClosed(null); } private void checkedListBox_ItemCheck(object sender, EventArgs e) { //统计选取的项目 Task.Run(() => { Thread.Sleep(100); Invoke(new Action(() => { string str = ""; for (int i = 0; i < checkedListBox.Items.Count; i++) { if (checkedListBox.GetItemChecked(i)) { str += $"{checkedListBox.Items[i].ParseToString()};"; } } this.Text = str.Trim(';'); string str1 = string.Join(";", this.Items.Cast().Select(o => o.ParseToString())); if (this.Text.Trim(';') == str1) { this.Text = this.DefaultText; } })); }); } } }