using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Drawing.Design; using System.Windows.Forms; using Sunny.UI; [DefaultProperty("Items")] [DefaultEvent("SelectedIndexChanged")] [ToolboxItem(true)] [Description("组合框控件")] [LookupBindingProperties("DataSource", "DisplayMember", "ValueMember", "SelectedValue")] public class UiComboBox : UIDropControl, IToolTip, IHideDropDown { private object filterSelectedItem; private object filterSelectedValue; private bool showFilter; private CurrencyManager dataManager; private List filterList = new List(); private bool SelectTextChange; private readonly UIComboBoxItem dropForm = new UIComboBoxItem(); private readonly UIComboBoxItem filterForm = new UIComboBoxItem(); private UIDropDown filterItemForm; private bool Wana_1; private BindingMemberInfo ValueMemberBindingMemberInfo; private IContainer components; [Browsable(false)] public override string[] FormTranslatorProperties => null; [DefaultValue(0)] [Category("SunnyUI")] [Description("垂直滚动条宽度,最小为原生滚动条宽度")] public int ScrollBarWidth { get { return ListBox.ScrollBarWidth; } set { ListBox.ScrollBarWidth = value; } } [DefaultValue(6)] [Category("SunnyUI")] [Description("垂直滚动条滑块宽度,最小为原生滚动条宽度")] public int ScrollBarHandleWidth { get { return ListBox.ScrollBarHandleWidth; } set { ListBox.ScrollBarHandleWidth = value; } } [DefaultValue(false)] [Description("显示清除按钮")] [Category("SunnyUI")] public bool ShowClearButton { get { return showClearButton; } set { showClearButton = value; } } [DefaultValue(false)] [Description("显示过滤")] [Category("SunnyUI")] public bool ShowFilter { get { return showFilter; } set { showFilter = value; if (value) { base.DropDownStyle = UIDropDownStyle.DropDown; } } } [DefaultValue(100)] [Description("过滤显示最大条目数")] [Category("SunnyUI")] public int FilterMaxCount { get; set; } = 100; [DefaultValue(false)] public bool Sorted { get { return ListBox.Sorted; } set { ListBox.Sorted = value; } } [DefaultValue(false)] [Description("过滤时删除字符串前面、后面的空格")] [Category("SunnyUI")] public bool TrimFilter { get; set; } [DefaultValue(false)] [Description("过滤时忽略大小写")] [Category("SunnyUI")] public bool FilterIgnoreCase { get; set; } private UIDropDown FilterItemForm { get { if (filterItemForm == null) { filterItemForm = new UIDropDown(filterForm); if (filterItemForm != null) { filterItemForm.VisibleChanged += FilterItemForm_VisibleChanged; } } return filterItemForm; } } private UIListBox ListBox => dropForm.ListBox; private UIListBox FilterListBox => filterForm.ListBox; [DefaultValue(25)] [Description("列表项高度")] [Category("SunnyUI")] public int ItemHeight { get { return ListBox.ItemHeight; } set { UIListBox filterListBox = FilterListBox; int itemHeight = (ListBox.ItemHeight = value); filterListBox.ItemHeight = itemHeight; } } [DefaultValue(8)] [Description("列表下拉最大个数")] [Category("SunnyUI")] public int MaxDropDownItems { get; set; } = 8; [DefaultValue(false)] [Description("不显示过滤可以自动调整下拉框宽度")] [Category("SunnyUI")] public bool DropDownAutoWidth { get; set; } public object DataSource { get { return ListBox.DataSource; } set { ListBox.DataSource = value; Box_DataSourceChanged(this, EventArgs.Empty); } } [DefaultValue(150)] [Description("下拉框宽度")] [Category("SunnyUI")] public int DropDownWidth { get; set; } [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] [Localizable(true)] [Editor("System.Windows.Forms.Design.ListControlStringCollectionEditor, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof(UITypeEditor))] [MergableProperty(false)] [Description("列表项")] [Category("SunnyUI")] public ListBox.ObjectCollection Items => ListBox.Items; [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] [Description("选中索引")] [Category("SunnyUI")] public int SelectedIndex { get { if (!ShowFilter) { return ListBox.SelectedIndex; } return -1; } set { if (!ShowFilter) { if (DataSource != null && value == -1 && SelectedIndex > 0) { Wana_1 = true; SelectedIndex = 0; Wana_1 = false; } ListBox.SelectedIndex = value; } } } [Browsable(false)] [Bindable(true)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] [Description("选中项")] [Category("SunnyUI")] public object SelectedItem { get { if (!ShowFilter) { return ListBox.SelectedItem; } return filterSelectedItem; } set { if (!ShowFilter) { ListBox.SelectedItem = value; } } } [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] [Description("选中文字")] [Category("SunnyUI")] public string SelectedText { get { if (base.DropDownStyle == UIDropDownStyle.DropDown) { return edit.SelectedText; } return Text; } } [Description("获取或设置要为此列表框显示的属性。")] [Category("SunnyUI")] [DefaultValue("")] [Editor("System.Windows.Forms.Design.DataMemberFieldEditor, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof(UITypeEditor))] [TypeConverter("System.Windows.Forms.Design.DataMemberFieldConverter, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] public string DisplayMember { get { return ListBox.DisplayMember; } set { ListBox.DisplayMember = value; Box_DisplayMemberChanged(this, EventArgs.Empty); } } [Description("获取或设置指示显示值的方式的格式说明符字符。")] [Category("SunnyUI")] [DefaultValue("")] [MergableProperty(false)] public string FormatString { get { return ListBox.FormatString; } set { UIListBox filterListBox = FilterListBox; string formatString = (ListBox.FormatString = value); filterListBox.FormatString = formatString; } } [Description("获取或设置指示显示值是否可以进行格式化操作。")] [Category("SunnyUI")] [DefaultValue(false)] public bool FormattingEnabled { get { return ListBox.FormattingEnabled; } set { UIListBox filterListBox = FilterListBox; bool formattingEnabled = (ListBox.FormattingEnabled = value); filterListBox.FormattingEnabled = formattingEnabled; } } [Description("获取或设置要为此列表框实际值的属性。")] [Category("SunnyUI")] [DefaultValue("")] [Editor("System.Windows.Forms.Design.DataMemberFieldEditor, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof(UITypeEditor))] public string ValueMember { get { return ListBox.ValueMember; } set { ListBox.ValueMember = value; ValueMemberBindingMemberInfo = new BindingMemberInfo(value); } } [DefaultValue(null)] [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] [Bindable(true)] public object SelectedValue { get { if (!ShowFilter) { return ListBox.SelectedValue; } return filterSelectedValue; } set { if (!ShowFilter) { ListBox.SelectedValue = value; } } } [DefaultValue(typeof(Color), "White")] public Color ItemFillColor { get { return ListBox.FillColor; } set { UIListBox filterListBox = FilterListBox; Color color2 = (ListBox.FillColor = value); filterListBox.FillColor = color2; } } [DefaultValue(typeof(Color), "48, 48, 48")] public Color ItemForeColor { get { return ListBox.ForeColor; } set { UIListBox filterListBox = FilterListBox; Color color2 = (ListBox.ForeColor = value); filterListBox.ForeColor = color2; } } [DefaultValue(typeof(Color), "243, 249, 255")] public Color ItemSelectForeColor { get { return ListBox.ItemSelectForeColor; } set { UIListBox filterListBox = FilterListBox; Color itemSelectForeColor = (ListBox.ItemSelectForeColor = value); filterListBox.ItemSelectForeColor = itemSelectForeColor; } } [DefaultValue(typeof(Color), "80, 160, 255")] public Color ItemSelectBackColor { get { return ListBox.ItemSelectBackColor; } set { UIListBox filterListBox = FilterListBox; Color itemSelectBackColor = (ListBox.ItemSelectBackColor = value); filterListBox.ItemSelectBackColor = itemSelectBackColor; } } [DefaultValue(typeof(Color), "220, 236, 255")] public Color ItemHoverColor { get { return ListBox.HoverColor; } set { UIListBox filterListBox = FilterListBox; Color hoverColor = (ListBox.HoverColor = value); filterListBox.HoverColor = hoverColor; } } [DefaultValue(typeof(Color), "80, 160, 255")] public Color ItemRectColor { get { return ListBox.RectColor; } set { UIListBox filterListBox = FilterListBox; Color color2 = (ListBox.RectColor = value); filterListBox.RectColor = color2; } } public event EventHandler SelectionChangeCommitted; public new event EventHandler TextChanged; public event EventHandler SelectedIndexChanged; public event EventHandler DataSourceChanged; public event EventHandler DisplayMemberChanged; public event EventHandler ValueMemberChanged; public event EventHandler SelectedValueChanged; public UiComboBox() { InitializeComponent(); ListBox.SelectedIndexChanged += Box_SelectedIndexChanged; ListBox.ValueMemberChanged += Box_ValueMemberChanged; ListBox.SelectedValueChanged += ListBox_SelectedValueChanged; ListBox.ItemsClear += ListBox_ItemsClear; ListBox.ItemsRemove += ListBox_ItemsRemove; ListBox.MouseClick += ListBox_MouseClick; filterForm.BeforeListClick += ListBox_Click; edit.TextChanged += Edit_TextChanged; edit.KeyDown += Edit_KeyDown; DropDownWidth = 150; fullControlSelect = true; base.MouseWheel += UIComboBox_MouseWheel; CreateInstance(); } private void UIComboBox_MouseWheel(object sender, MouseEventArgs e) { if (!ShowFilter && base.DropDownStyle == UIDropDownStyle.DropDownList) { if (e.Delta <= -100 && SelectedIndex < Items.Count) { SelectedIndex++; } if (e.Delta >= 100 && SelectedIndex > 0) { SelectedIndex--; } } } private void ListBox_MouseClick(object sender, MouseEventArgs e) { if (((UIListBox)sender).IndexFromPoint(e.X, e.Y) != -1) { this.SelectionChangeCommitted?.Invoke(this, EventArgs.Empty); } } public override void Clear() { base.Clear(); if (DataSource != null) { DataSource = null; } else { ListBox.Items.Clear(); } } private void ListBox_Click(object sender, EventArgs e) { SelectTextChange = true; filterSelectedItem = filterList[(int)sender]; filterSelectedValue = GetItemValue(filterSelectedItem); Text = GetItemText(filterSelectedItem); edit.SelectionStart = Text.Length; this.SelectedValueChanged?.Invoke(this, EventArgs.Empty); SelectTextChange = false; } private void ShowDropDownFilter() { if (Text.IsNullOrEmpty() && ShowFilter) { FillFilterTextEmpty(); } FilterItemForm.AutoClose = false; if (!FilterItemForm.Visible) { filterForm.Style = base.StyleDropDown; if (base.StyleDropDown != UIStyle.Inherited) { filterForm.Style = base.StyleDropDown; } else { filterForm.Style = UIStyles.Style; } FilterItemForm.Show(this, new Size((DropDownWidth < base.Width) ? base.Width : DropDownWidth, CalcItemFormHeight())); edit.Focus(); } } private void Edit_KeyDown(object sender, KeyEventArgs e) { if (ShowFilter) { if (e.KeyCode == Keys.Down || e.KeyCode == Keys.Up) { if (!FilterItemForm.Visible) { ShowDropDownFilter(); } int count = filterForm.ListBox.Items.Count; int selectedIndex = filterForm.ListBox.SelectedIndex; if (count > 0) { if (e.KeyCode == Keys.Down && selectedIndex < count - 1) { filterForm.ListBox.SelectedIndex++; } if (e.KeyCode == Keys.Up && selectedIndex > 0) { filterForm.ListBox.SelectedIndex--; } } } else if (e.KeyCode == Keys.Escape) { FilterItemForm.Close(); } else if (e.KeyCode == Keys.Return) { if (FilterItemForm.Visible) { int count2 = filterForm.ListBox.Items.Count; int selectedIndex2 = filterForm.ListBox.SelectedIndex; if (count2 > 0 && selectedIndex2 >= 0 && selectedIndex2 < count2) { SelectTextChange = true; filterSelectedItem = filterList[selectedIndex2]; filterSelectedValue = GetItemValue(filterSelectedItem); Text = GetItemText(filterSelectedItem); edit.SelectionStart = Text.Length; this.SelectedValueChanged?.Invoke(this, EventArgs.Empty); SelectTextChange = false; } FilterItemForm.Close(); } else { ShowDropDownFilter(); } } else { base.OnKeyDown(e); } } else if (e.KeyCode == Keys.Return) { ShowDropDown(); } else if (e.KeyCode == Keys.Escape) { base.ItemForm.Close(); } else { base.OnKeyDown(e); } } protected override void DropDownStyleChanged() { if (base.DropDownStyle == UIDropDownStyle.DropDownList) { showFilter = false; } } private void SetDataConnection() { if (ShowFilter && base.DropDownStyle == UIDropDownStyle.DropDown && DataSource != null && DisplayMember.IsValid()) { dataManager = (CurrencyManager)BindingContext[DataSource, new BindingMemberInfo(DisplayMember).BindingPath]; } } private object GetItemValue(object item) { if (dataManager == null) { return item; } if (ValueMember.IsNullOrWhiteSpace()) { return null; } return dataManager.GetItemProperties().Find(ValueMemberBindingMemberInfo.BindingField, ignoreCase: true)?.GetValue(item); } public Control ExToolTipControl() { return edit; } public int FindString(string s) { return ListBox.FindString(s); } public int FindString(string s, int startIndex) { return ListBox.FindString(s, startIndex); } public int FindStringExact(string s) { return ListBox.FindStringExact(s); } public int FindStringExact(string s, int startIndex) { return ListBox.FindStringExact(s, startIndex); } private void ListBox_ItemsRemove(object sender, EventArgs e) { if (ListBox.Count == 0 && base.DropDownStyle == UIDropDownStyle.DropDownList) { Text = ""; edit.Text = ""; } } private void ListBox_ItemsClear(object sender, EventArgs e) { if (base.DropDownStyle == UIDropDownStyle.DropDownList) { Text = ""; edit.Text = ""; } } private void Edit_TextChanged(object sender, EventArgs e) { this.TextChanged?.Invoke(this, e); if (!ShowFilter) { if (!SelectTextChange) { if (Text.IsValid()) { ListBox.ListBox.Text = Text; return; } SelectTextChange = true; SelectedIndex = -1; edit.Text = ""; SelectTextChange = false; } } else { if (base.DropDownStyle == UIDropDownStyle.DropDownList) { return; } if (edit.Focused && Text.IsValid()) { ShowDropDownFilter(); } if (Text.IsValid()) { string text = Text; if (TrimFilter) { text = text.Trim(); } filterForm.ListBox.Items.Clear(); filterList.Clear(); if (DataSource == null) { foreach (object item in Items) { if (FilterIgnoreCase) { if (item.ToString().ToUpper().Contains(text.ToUpper())) { filterList.Add(item.ToString()); if (filterList.Count > FilterMaxCount) { break; } } } else if (item.ToString().Contains(text)) { filterList.Add(item.ToString()); if (filterList.Count > FilterMaxCount) { break; } } } } else if (dataManager != null) { for (int i = 0; i < Items.Count; i++) { if (FilterIgnoreCase) { if (GetItemText(dataManager.List[i]).ToUpper().Contains(text.ToUpper())) { filterList.Add(dataManager.List[i]); if (filterList.Count > FilterMaxCount) { break; } } } else if (GetItemText(dataManager.List[i]).Contains(text)) { filterList.Add(dataManager.List[i]); if (filterList.Count > FilterMaxCount) { break; } } } } { foreach (object filter in filterList) { filterForm.ListBox.Items.Add(GetItemText(filter)); } return; } } FillFilterTextEmpty(); filterSelectedItem = null; filterSelectedValue = null; this.SelectedValueChanged?.Invoke(this, EventArgs.Empty); } } private void FillFilterTextEmpty() { filterForm.ListBox.Items.Clear(); filterList.Clear(); if (DataSource == null) { foreach (object item in Items) { filterList.Add(item.ToString()); } } else if (dataManager != null) { for (int i = 0; i < Items.Count; i++) { filterList.Add(dataManager.List[i]); } } foreach (object filter in filterList) { filterForm.ListBox.Items.Add(GetItemText(filter)); } } private void ListBox_SelectedValueChanged(object sender, EventArgs e) { if (!ShowFilter) { this.SelectedValueChanged?.Invoke(this, e); } } private void Box_ValueMemberChanged(object sender, EventArgs e) { this.ValueMemberChanged?.Invoke(this, e); } private void Box_DisplayMemberChanged(object _, EventArgs e) { this.DisplayMemberChanged?.Invoke(this, e); SetDataConnection(); } private void Box_DataSourceChanged(object _, EventArgs e) { this.DataSourceChanged?.Invoke(this, e); SetDataConnection(); } private void Box_SelectedIndexChanged(object sender, EventArgs e) { SelectTextChange = true; if (!ShowFilter) { if (ListBox.SelectedItem != null) { Text = ListBox.GetItemText(ListBox.SelectedItem); } else { Text = ""; } } SelectTextChange = false; if (!Wana_1) { this.SelectedIndexChanged?.Invoke(this, e); } } protected override void ItemForm_ValueChanged(object sender, object value) { Invalidate(); } private void FilterItemForm_VisibleChanged(object sender, EventArgs e) { dropSymbol = base.SymbolNormal; if (filterItemForm.Visible) { dropSymbol = base.SymbolDropDown; } Invalidate(); } protected override void CreateInstance() { base.ItemForm = new UIDropDown(dropForm); } protected override int CalcItemFormHeight() { int num = base.ItemForm.Height - base.ItemForm.ClientRectangle.Height; return 4 + Math.Min(ListBox.Items.Count, MaxDropDownItems) * ItemHeight + num; } private void UIComboBox_FontChanged(object sender, EventArgs e) { if (base.ItemForm != null) { ListBox.Font = Font; } if (filterForm != null) { filterForm.ListBox.Font = Font; } } public void ShowDropDown() { UIComboBox_ButtonClick(this, EventArgs.Empty); } public void HideDropDown() { try { if (!ShowFilter) { if (base.ItemForm != null && base.ItemForm.Visible) { base.ItemForm.Close(); } } else if (FilterItemForm != null && FilterItemForm.Visible) { FilterItemForm.Close(); } } catch { } } private void UIComboBox_ButtonClick(object sender, EventArgs e) { if (NeedDrawClearButton) { NeedDrawClearButton = false; Text = ""; if (!showFilter) { while (dropForm.ListBox.SelectedIndex != -1) { dropForm.ListBox.SelectedIndex = -1; } } else { while (filterForm.ListBox.SelectedIndex != -1) { filterForm.ListBox.SelectedIndex = -1; } } Invalidate(); } else if (!ShowFilter) { if (Items.Count <= 0) { return; } int num = base.Width; if (DropDownAutoWidth) { if (DataSource == null) { for (int i = 0; i < Items.Count; i++) { num = Math.Max(TextRenderer.MeasureText(Items[i].ToString(), Font).Width + ScrollBarInfo.VerticalScrollBarWidth() + 6, num); } } else { for (int j = 0; j < Items.Count; j++) { num = Math.Max(TextRenderer.MeasureText(dropForm.ListBox.GetItemText(Items[j]), Font).Width + ScrollBarInfo.VerticalScrollBarWidth() + 6, num); } } } else { num = Math.Max(DropDownWidth, num); } if (base.StyleDropDown != UIStyle.Inherited) { dropForm.Style = base.StyleDropDown; } base.ItemForm.Show(this, new Size(num, CalcItemFormHeight())); } else { if (base.StyleDropDown != UIStyle.Inherited) { filterForm.Style = base.StyleDropDown; } if (FilterItemForm.Visible) { FilterItemForm.Close(); } else { ShowDropDownFilter(); } } } public override void SetStyleColor(UIBaseStyle uiColor) { base.SetStyleColor(uiColor); ListBox.SetStyleColor(uiColor.DropDownStyle); FilterListBox.SetStyleColor(uiColor.DropDownStyle); } public override void ResetText() { Clear(); } public string GetItemText(object item) { return ListBox.GetItemText(item); } private void UIComboBox_KeyDown(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.Return && !ShowFilter) { ShowDropDown(); } } private void edit_Leave(object sender, EventArgs e) { HideDropDown(); } protected override void Dispose(bool disposing) { if (disposing && components != null) { components.Dispose(); } dropForm?.Dispose(); filterForm?.Dispose(); filterItemForm?.Dispose(); base.Dispose(disposing); } private void InitializeComponent() { base.SuspendLayout(); base.edit.Leave += new System.EventHandler(edit_Leave); base.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None; base.Name = "UIComboBox"; base.KeyDown += new System.Windows.Forms.KeyEventHandler(UIComboBox_KeyDown); base.ButtonClick += new System.EventHandler(UIComboBox_ButtonClick); base.FontChanged += new System.EventHandler(UIComboBox_FontChanged); base.ResumeLayout(false); base.PerformLayout(); } }