using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.Diagnostics;
namespace CheckComboBoxTest {
public class CheckedComboBox : ComboBox {
internal class Dropdown : Form {
internal class CCBoxEventArgs : EventArgs {
private bool assignValues;
public bool AssignValues {
get { return assignValues; }
set { assignValues = value; }
}
private EventArgs e;
public EventArgs EventArgs {
get { return e; }
set { e = value; }
}
public CCBoxEventArgs(EventArgs e, bool assignValues) : base() {
this.e = e;
this.assignValues = assignValues;
}
}
internal class CustomCheckedListBox : CheckedListBox {
private int curSelIndex = -1;
public CustomCheckedListBox() : base() {
this.SelectionMode = SelectionMode.One;
this.HorizontalScrollbar = true;
}
protected override void OnKeyDown(KeyEventArgs e) {
if (e.KeyCode == Keys.Enter) {
// Enact selection.
((CheckedComboBox.Dropdown) Parent).OnDeactivate(new CCBoxEventArgs(null, true));
e.Handled = true;
} else if (e.KeyCode == Keys.Escape) {
((CheckedComboBox.Dropdown) Parent).OnDeactivate(new CCBoxEventArgs(null, false));
e.Handled = true;
} else if (e.KeyCode == Keys.Delete) {
for (int i = 0; i < Items.Count; i++) {
SetItemChecked(i, e.Shift);
}
e.Handled = true;
}
base.OnKeyDown(e);
}
protected override void OnMouseMove(MouseEventArgs e) {
base.OnMouseMove(e);
int index = IndexFromPoint(e.Location);
Debug.WriteLine("Mouse over item: " + (index >= 0 ? GetItemText(Items[index]) : "None"));
if ((index >= 0) && (index != curSelIndex)) {
curSelIndex = index;
SetSelected(index, true);
}
}
}
private CheckedComboBox ccbParent;
private string oldStrValue = "";
public bool ValueChanged {
get {
string newStrValue = ccbParent.Text;
if ((oldStrValue.Length > 0) && (newStrValue.Length > 0)) {
return (oldStrValue.CompareTo(newStrValue) != 0);
} else {
return (oldStrValue.Length != newStrValue.Length);
}
}
}
bool[] checkedStateArr;
private bool dropdownClosed = true;
private CustomCheckedListBox cclb;
public CustomCheckedListBox List {
get { return cclb; }
set { cclb = value; }
}
public Dropdown(CheckedComboBox ccbParent) {
this.ccbParent = ccbParent;
InitializeComponent();
this.ShowInTaskbar = false;
this.cclb.ItemCheck += new System.Windows.Forms.ItemCheckEventHandler(this.cclb_ItemCheck);
}
private void InitializeComponent() {
this.cclb = new CustomCheckedListBox();
this.SuspendLayout();
//
// cclb
//
this.cclb.BorderStyle = System.Windows.Forms.BorderStyle.None;
this.cclb.Dock = System.Windows.Forms.DockStyle.Fill;
this.cclb.FormattingEnabled = true;
this.cclb.Location = new System.Drawing.Point(0, 0);
this.cclb.Name = "cclb";
this.cclb.Size = new System.Drawing.Size(47, 15);
this.cclb.TabIndex = 0;
//
// Dropdown
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackColor = System.Drawing.SystemColors.Menu;
this.ClientSize = new System.Drawing.Size(47, 16);
this.ControlBox = false;
this.Controls.Add(this.cclb);
this.ForeColor = System.Drawing.SystemColors.ControlText;
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
this.MinimizeBox = false;
this.Name = "ccbParent";
this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
this.ResumeLayout(false);
}
public string GetCheckedItemsStringValue() {
StringBuilder sb = new StringBuilder("");
for (int i = 0; i < cclb.CheckedItems.Count; i++) {
sb.Append(cclb.GetItemText(cclb.CheckedItems[i])).Append(ccbParent.ValueSeparator);
}
if (sb.Length > 0) {
sb.Remove(sb.Length - ccbParent.ValueSeparator.Length, ccbParent.ValueSeparator.Length);
}
return sb.ToString();
}
public void CloseDropdown(bool enactChanges) {
if (dropdownClosed) {
return;
}
Debug.WriteLine("CloseDropdown");
if (enactChanges) {
ccbParent.SelectedIndex = -1;
ccbParent.Text = GetCheckedItemsStringValue();
} else {
for (int i = 0; i < cclb.Items.Count; i++) {
cclb.SetItemChecked(i, checkedStateArr[i]);
}
}
dropdownClosed = true;
ccbParent.Focus();
this.Hide();
ccbParent.OnDropDownClosed(new CCBoxEventArgs(null, false));
}
protected override void OnActivated(EventArgs e) {
Debug.WriteLine("OnActivated");
base.OnActivated(e);
dropdownClosed = false;
oldStrValue = ccbParent.Text;
checkedStateArr = new bool[cclb.Items.Count];
for (int i = 0; i < cclb.Items.Count; i++) {
checkedStateArr[i] = cclb.GetItemChecked(i);
}
}
protected override void OnDeactivate(EventArgs e) {
Debug.WriteLine("OnDeactivate");
base.OnDeactivate(e);
CCBoxEventArgs ce = e as CCBoxEventArgs;
if (ce != null) {
CloseDropdown(ce.AssignValues);
} else {
CloseDropdown(true);
}
}
private void cclb_ItemCheck(object sender, ItemCheckEventArgs e) {
if (ccbParent.ItemCheck != null) {
ccbParent.ItemCheck(sender, e);
}
}
}
private System.ComponentModel.IContainer components = null;
private Dropdown dropdown;
private string valueSeparator;
public string ValueSeparator {
get { return valueSeparator; }
set { valueSeparator = value; }
}
public bool CheckOnClick {
get { return dropdown.List.CheckOnClick; }
set { dropdown.List.CheckOnClick = value; }
}
public new string DisplayMember {
get { return dropdown.List.DisplayMember; }
set { dropdown.List.DisplayMember = value; }
}
public new CheckedListBox.ObjectCollection Items {
get { return dropdown.List.Items; }
}
public CheckedListBox.CheckedItemCollection CheckedItems {
get { return dropdown.List.CheckedItems; }
}
public CheckedListBox.CheckedIndexCollection CheckedIndices {
get { return dropdown.List.CheckedIndices; }
}
public bool ValueChanged {
get { return dropdown.ValueChanged; }
}
public event ItemCheckEventHandler ItemCheck;
public CheckedComboBox() : base() {
this.DrawMode = DrawMode.OwnerDrawVariable;
this.valueSeparator = ", ";
this.DropDownHeight = 1;
this.DropDownStyle = ComboBoxStyle.DropDown;
this.dropdown = new Dropdown(this);
this.CheckOnClick = true;
}
protected override void Dispose(bool disposing) {
if (disposing && (components != null)) {
components.Dispose();
}
base.Dispose(disposing);
}
protected override void OnDropDown(EventArgs e) {
base.OnDropDown(e);
DoDropDown();
}
private void DoDropDown() {
if (!dropdown.Visible) {
Rectangle rect = RectangleToScreen(this.ClientRectangle);
dropdown.Location = new Point(rect.X, rect.Y + this.Size.Height);
int count = dropdown.List.Items.Count;
if (count > this.MaxDropDownItems) {
count = this.MaxDropDownItems;
} else if (count == 0) {
count = 1;
}
dropdown.Size = new Size(this.Size.Width, (dropdown.List.ItemHeight) * count + 2);
dropdown.Show(this);
}
}
protected override void OnDropDownClosed(EventArgs e) {
if (e is Dropdown.CCBoxEventArgs) {
base.OnDropDownClosed(e);
}
}
protected override void OnKeyDown(KeyEventArgs e) {
if (e.KeyCode == Keys.Down) {
OnDropDown(null);
}
e.Handled = !e.Alt && !(e.KeyCode == Keys.Tab) &&
!((e.KeyCode == Keys.Left) || (e.KeyCode == Keys.Right) || (e.KeyCode == Keys.Home) || (e.KeyCode == Keys.End));
base.OnKeyDown(e);
}
protected override void OnKeyPress(KeyPressEventArgs e) {
e.Handled = true;
base.OnKeyPress(e);
}
public bool GetItemChecked(int index) {
if (index < 0 || index > Items.Count) {
throw new ArgumentOutOfRangeException("index", "value out of range");
} else {
return dropdown.List.GetItemChecked(index);
}
}
public void SetItemChecked(int index, bool isChecked) {
if (index < 0 || index > Items.Count) {
throw new ArgumentOutOfRangeException("index", "value out of range");
} else {
dropdown.List.SetItemChecked(index, isChecked);
this.Text = dropdown.GetCheckedItemsStringValue();
}
}
public CheckState GetItemCheckState(int index) {
if (index < 0 || index > Items.Count) {
throw new ArgumentOutOfRangeException("index", "value out of range");
} else {
return dropdown.List.GetItemCheckState(index);
}
}
public void SetItemCheckState(int index, CheckState state) {
if (index < 0 || index > Items.Count) {
throw new ArgumentOutOfRangeException("index", "value out of range");
} else {
dropdown.List.SetItemCheckState(index, state);
this.Text = dropdown.GetCheckedItemsStringValue();
}
}
}
}
效果图: