SunnyUI/SunnyUI/Controls/UIComboBox.cs

394 lines
13 KiB
C#
Raw Normal View History

2020-05-11 21:11:29 +08:00
/******************************************************************************
* SunnyUI
* CopyRight (C) 2012-2020 ShenYongHua().
* QQ群56829229 QQ17612584 EMailSunnyUI@qq.com
*
* Blog: https://www.cnblogs.com/yhuse
* Gitee: https://gitee.com/yhuse/SunnyUI
* GitHub: https://github.com/yhuse/SunnyUI
*
* SunnyUI.dll can be used for free under the GPL-3.0 license.
* If you use this code, please keep this note.
* 使
******************************************************************************
* : UIComboBox.cs
* :
* : V2.2
* : 2020-01-01
*
* 2020-01-01: V2.2.0
* 2020-06-11: V2.2.5 DataSource
2020-05-11 21:11:29 +08:00
******************************************************************************/
using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Design;
using System.Windows.Forms;
2020-06-11 23:53:51 +08:00
using static System.Windows.Forms.ComboBox;
2020-05-11 21:11:29 +08:00
namespace Sunny.UI
{
[DefaultProperty("Items")]
[DefaultEvent("SelectedIndexChanged")]
[ToolboxItem(true)]
2020-06-11 23:53:51 +08:00
[LookupBindingProperties("DataSource", "DisplayMember", "ValueMember", "SelectedValue")]
2020-05-11 21:11:29 +08:00
public sealed partial class UIComboBox : UIDropControl
{
public UIComboBox()
{
InitializeComponent();
2020-06-11 23:53:51 +08:00
box.SelectedIndexChanged += Box_SelectedIndexChanged;
box.DataSourceChanged += Box_DataSourceChanged;
box.DisplayMemberChanged += Box_DisplayMemberChanged;
box.ValueMemberChanged += Box_ValueMemberChanged;
DropDownWidth = 150;
2020-06-11 23:53:51 +08:00
}
private void Box_ValueMemberChanged(object sender, EventArgs e)
{
ValueMemberChanged?.Invoke(sender, e);
}
private void Box_DisplayMemberChanged(object sender, EventArgs e)
{
DisplayMemberChanged?.Invoke(sender, e);
}
private void Box_DataSourceChanged(object sender, EventArgs e)
{
DataSourceChanged?.Invoke(sender, e);
}
private void Box_SelectedIndexChanged(object sender, EventArgs e)
{
Text = box.GetItemText(box.SelectedItem);
GetSelectedValue();
SelectedValueChanged?.Invoke(this, e);
SelectedIndexChanged?.Invoke(this, e);
2020-06-11 23:53:51 +08:00
}
2020-05-11 21:11:29 +08:00
public event EventHandler SelectedIndexChanged;
2020-06-11 23:53:51 +08:00
public event EventHandler DataSourceChanged;
public event EventHandler DisplayMemberChanged;
public event EventHandler ValueMemberChanged;
public event EventHandler SelectedValueChanged;
public readonly ComboBox box = new ComboBox();
2020-06-11 23:53:51 +08:00
2020-05-11 21:11:29 +08:00
protected override void ItemForm_ValueChanged(object sender, object value)
{
SelectedIndex = ListBox.SelectedIndex;
Box_SelectedIndexChanged(null, null);
2020-05-11 21:11:29 +08:00
Invalidate();
}
private readonly UIComboBoxItem dropForm = new UIComboBoxItem();
2020-05-11 21:11:29 +08:00
protected override void CreateInstance()
{
ItemForm = new UIDropDown(dropForm);
2020-05-11 21:11:29 +08:00
}
protected override int CalcItemFormHeight()
{
int interval = ItemForm.Height - ItemForm.ClientRectangle.Height;
return 4 + Math.Min(ListBox.Items.Count, MaxDropDownItems) * ItemHeight + interval;
2020-05-11 21:11:29 +08:00
}
private UIListBox ListBox
{
get => dropForm.ListBox;
2020-05-11 21:11:29 +08:00
}
[DefaultValue(25)]
[Description("列表项高度"), Category("SunnyUI")]
2020-05-11 21:11:29 +08:00
public int ItemHeight
{
get => ListBox.ItemHeight;
set => ListBox.ItemHeight = value;
}
[DefaultValue(8)]
[Description("列表下拉最大个数"), Category("SunnyUI")]
2020-05-11 21:11:29 +08:00
public int MaxDropDownItems { get; set; } = 8;
2020-06-11 23:53:51 +08:00
private void UIComboBox_FontChanged(object sender, EventArgs e)
2020-05-11 21:11:29 +08:00
{
2020-06-11 23:53:51 +08:00
if (ItemForm != null)
2020-05-11 21:11:29 +08:00
{
2020-06-11 23:53:51 +08:00
ListBox.Font = Font;
2020-05-11 21:11:29 +08:00
}
}
private void UIComboBox_ButtonClick(object sender, EventArgs e)
{
ListBox.Items.Clear();
2020-05-11 21:11:29 +08:00
if (Items.Count == 0 || ItemForm.Visible)
{
return;
}
foreach (var data in Items)
2020-05-11 21:11:29 +08:00
{
ListBox.Items.Add(GetItemText(data));
2020-05-11 21:11:29 +08:00
}
2020-06-11 23:53:51 +08:00
ListBox.SelectedIndex = SelectedIndex;
ItemForm.Show(this, new Size(DropDownWidth < Width ? Width : DropDownWidth, CalcItemFormHeight()));
2020-05-11 21:11:29 +08:00
}
public override void SetStyleColor(UIBaseStyle uiColor)
{
base.SetStyleColor(uiColor);
if (uiColor.IsCustom()) return;
ListBox.SetStyleColor(uiColor);
}
2020-06-11 23:53:51 +08:00
private object dataSource;
2020-06-11 23:53:51 +08:00
[DefaultValue(null), RefreshProperties(RefreshProperties.Repaint), AttributeProvider(typeof(IListSource))]
[Description("数据源"), Category("SunnyUI")]
2020-06-11 23:53:51 +08:00
public object DataSource
{
get => dataSource;
set
{
SetDataConnection(value, new BindingMemberInfo(DisplayMember));
dataSource = value;
box.Items.Clear();
if (dataManager != null)
{
foreach (var obj in dataManager.List)
{
box.Items.Add(obj);
}
}
}
2020-06-11 23:53:51 +08:00
}
private bool inSetDataConnection;
private CurrencyManager dataManager;
private void SetDataConnection(object newDataSource, BindingMemberInfo newDisplayMember)
2020-06-11 23:53:51 +08:00
{
bool dataSourceChanged = dataSource != newDataSource;
bool displayMemberChanged = !DisplayMember.Equals(newDisplayMember.BindingPath);
if (inSetDataConnection)
{
return;
}
try
{
2020-07-28 21:01:40 +08:00
inSetDataConnection = true;
if (dataSourceChanged || displayMemberChanged)
{
CurrencyManager newDataManager = null;
if (newDataSource != null && newDataSource != Convert.DBNull)
{
newDataManager = (CurrencyManager)BindingContext[newDataSource, newDisplayMember.BindingPath];
}
dataManager = newDataManager;
}
}
finally
{
inSetDataConnection = false;
}
2020-06-11 23:53:51 +08:00
}
[DefaultValue(150)]
[Description("下拉框宽度"), Category("SunnyUI")]
public int DropDownWidth { get; set; }
2020-06-11 23:53:51 +08:00
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
[Editor("System.Windows.Forms.Design.ListControlStringCollectionEditor, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof(UITypeEditor))]
[Localizable(true)]
[MergableProperty(false)]
[Description("下拉显示项"), Category("SunnyUI")]
2020-06-11 23:53:51 +08:00
public ObjectCollection Items
{
get => box.Items;
}
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[Description("选中索引"), Category("SunnyUI")]
2020-06-11 23:53:51 +08:00
public int SelectedIndex
{
get => box.SelectedIndex;
set => box.SelectedIndex = value;
}
[Browsable(false), Bindable(true), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[Description("选中项"), Category("SunnyUI")]
2020-06-11 23:53:51 +08:00
public object SelectedItem
{
get => box.SelectedItem;
set => box.SelectedItem = value;
}
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[Description("选中文字"), Category("SunnyUI")]
2020-06-11 23:53:51 +08:00
public string SelectedText
{
get
{
if (DropDownStyle == UIDropDownStyle.DropDown)
{
return edit.SelectedText;
}
else
{
return Text;
}
}
2020-06-11 23:53:51 +08:00
}
public override void ResetText()
{
Clear();
2020-06-11 23:53:51 +08:00
}
[Description("获取或设置要为此列表框显示的属性。"), Category("SunnyUI")]
2020-06-11 23:53:51 +08:00
[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 => box.DisplayMember;
set
{
SetDataConnection(dataSource, new BindingMemberInfo(value));
box.DisplayMember = value;
}
2020-06-11 23:53:51 +08:00
}
[Description("获取或设置指示显示值的方式的格式说明符字符。"), Category("SunnyUI")]
2020-06-11 23:53:51 +08:00
[DefaultValue("")]
[Editor("System.Windows.Forms.Design.FormatStringEditor, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof(UITypeEditor))]
[MergableProperty(false)]
public string FormatString
{
get => box.FormatString;
set => box.FormatString = value;
}
[Description("获取或设置指示显示值是否可以进行格式化操作。"), Category("SunnyUI")]
2020-06-11 23:53:51 +08:00
[DefaultValue(false)]
public bool FormattingEnabled
{
get => box.FormattingEnabled;
set => box.FormattingEnabled = value;
}
[Description("获取或设置要为此列表框实际值的属性。"), Category("SunnyUI")]
2020-06-11 23:53:51 +08:00
[DefaultValue("")]
[Editor("System.Windows.Forms.Design.DataMemberFieldEditor, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof(UITypeEditor))]
public string ValueMember
{
get => box.ValueMember;
set => box.ValueMember = value;
}
private object selectedValue;
private void GetSelectedValue()
{
if (SelectedIndex != -1 && dataManager != null)
{
selectedValue = FilterItemOnProperty(SelectedItem, ValueMember);
}
else
{
selectedValue = null;
}
}
2020-06-11 23:53:51 +08:00
[
DefaultValue(null),
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
Bindable(true)
]
2020-06-11 23:53:51 +08:00
public object SelectedValue
{
get
{
GetSelectedValue();
return selectedValue;
}
set
{
selectedValue = value;
if (value == null)
{
return;
}
if (dataManager != null)
{
int index = DataManagerFind(value);
SelectedIndex = index;
}
}
}
private int DataManagerFind(object value)
{
if (dataManager == null) return -1;
for (int i = 0; i < dataManager.List.Count; i++)
{
var item = dataManager.List[i];
if (FilterItemOnProperty(item, ValueMember).Equals(value))
{
return i;
}
}
return -1;
}
private object FilterItemOnProperty(object item, string field)
{
if (item != null && field.Length > 0)
{
try
{
// if we have a dataSource, then use that to display the string
PropertyDescriptor descriptor;
if (dataManager != null)
descriptor = dataManager.GetItemProperties().Find(field, true);
else
descriptor = TypeDescriptor.GetProperties(item).Find(field, true);
if (descriptor != null)
{
item = descriptor.GetValue(item);
}
}
catch
{
return null;
}
}
return item;
2020-06-11 23:53:51 +08:00
}
public string GetItemText(object item)
{
return box.GetItemText(item);
}
2020-05-11 21:11:29 +08:00
}
}