using System; using System.Collections.Generic; using System.ComponentModel; using System.Windows.Forms; namespace Microsoft.Win32.TaskScheduler { /// /// A check list in a drop down combo box. /// [System.Drawing.ToolboxBitmap(typeof(Microsoft.Win32.TaskScheduler.TaskEditDialog), "Control")] public partial class DropDownCheckList : CustomComboBox { private System.Windows.Forms.CheckedListBox checkedListBox1; private int lastCheckHash = 0; private Timer onCheckTimer; private bool privateSet = false; /// /// Initializes a new instance of the class. /// public DropDownCheckList() { this.onCheckTimer = new Timer { Interval = 150 }; this.onCheckTimer.Tick += onCheckTimer_Tick; this.checkedListBox1 = new System.Windows.Forms.CheckedListBox() { BorderStyle = System.Windows.Forms.BorderStyle.None, CheckOnClick = true, FormattingEnabled = true, Location = new System.Drawing.Point(17, 35), MultiColumn = false, Name = "checkedListBox1", Size = new System.Drawing.Size(187, 105), TabIndex = 0 }; this.checkedListBox1.ItemCheck += new ItemCheckEventHandler(checkedListBox1_ItemCheck); base.DropDownControl = this.checkedListBox1; } /// /// Occurs when the property changes. /// [Category("Action"), Description("Occurs when the SelectedItems property changes.")] public event EventHandler SelectedItemsChanged; /// /// Gets or sets a value indicating whether to allow only one checked item. /// /// true if allowing only one checked item; otherwise, false. [Category("Behavior"), DefaultValue(false)] public bool AllowOnlyOneCheckedItem { get; set; } /// /// Gets or sets the text used on the Check All Items item that, when clicked, will check all the other items. /// /// The text. [DefaultValue((string)null), Category("Appearance"), Localizable(true)] public string CheckAllText { get; set; } /// /// Gets or sets the logical AND value of all checked items. /// /// The checked flags bitwise value. [DefaultValue(0L), Category("Data"), Browsable(false)] public long CheckedFlagValue { get { long ret = 0; for (int i = 0; i < checkedListBox1.CheckedItems.Count; i++) { object o = checkedListBox1.CheckedItems[i]; if (o is DropDownCheckListItem) o = ((DropDownCheckListItem)o).Value; try { ret |= Convert.ToInt64(o); } catch {} } return ret; } set { privateSet = true; for (int i = 0; i < checkedListBox1.Items.Count; i++) { long? val = null; object o = checkedListBox1.Items[i]; if (checkedListBox1.Items[i] is DropDownCheckListItem) o = ((DropDownCheckListItem)o).Value; try { val = Convert.ToInt64(o); } catch { } if (val.HasValue && (val.Value & value) == val.Value) this.checkedListBox1.SetItemCheckState(i, CheckState.Checked); else this.checkedListBox1.SetItemCheckState(i, CheckState.Unchecked); } privateSet = false; CheckedItemsChanged(); } } /// /// Gets or sets a value indicating whether formatting is applied to the property of the . /// /// /// true if formatting of the property is enabled; otherwise, false. The default is false. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public new bool FormattingEnabled { get { return base.FormattingEnabled; } set { base.FormattingEnabled = value; } } /// /// Gets the list of all check list items. /// /// The items. [DesignerSerializationVisibility(DesignerSerializationVisibility.Content), Category("Data")] public new CheckedListBox.ObjectCollection Items { get { return this.checkedListBox1.Items; } } /// /// Gets or sets a value indicating whether to display the list with multiple columns. /// /// true if multi-column; otherwise, false. [DefaultValue(false), Category("Appearance")] public bool MultiColumnList { get { return this.checkedListBox1.MultiColumn; } set { this.checkedListBox1.MultiColumn = value; } } /// /// Gets the selected items. /// /// The selected items. [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public DropDownCheckListItem[] SelectedItems { get { var c = this.checkedListBox1.CheckedItems; DropDownCheckListItem[] ret = new DropDownCheckListItem[c.Count]; for (int i = 0; i < ret.Length; i++) { ret[i] = c[i] as DropDownCheckListItem; if (ret[i] == null) ret[i] = new DropDownCheckListItem(c[i]); } return ret; } } /// /// Gets or sets a value indicating whether the items in the combo box are sorted. /// /// true if the combo box is sorted; otherwise, false. The default is false. /// /// An attempt was made to sort a that is attached to a data source. /// /// /// /// /// /// /// public new bool Sorted { get { return this.checkedListBox1.Sorted; } set { this.checkedListBox1.Sorted = value; } } /// /// Checks the matching items. /// /// The match. /// if set to true keep existing checked items. public void CheckItems(Predicate match, bool keepExisting = false) { for (int i = 0; i < this.checkedListBox1.Items.Count; i++) { if (match == null || match(this.checkedListBox1.Items[i])) this.SetItemChecked(i, true); else if (!keepExisting) this.SetItemChecked(i, false); } } /// /// Unchecks all items. /// public void UncheckAllItems() { CheckItems(o => false); } /// /// Gets the check state of the specified item. /// /// The index of the item. /// true if item is checked; otherwise, false. public bool GetItemChecked(int index) { return this.checkedListBox1.GetItemChecked(index); } /// /// Initializes the check list from an enumerated type. /// /// The enumerated type. /// The that holds the display text for each enumerated value. /// (Optional) The prefix used in front of the enumeration value to pull from the resource file. If null, then this value defaults to the name of the enumerated type specified by . /// (Optional) The excluded items from the enumerated type. public void InitializeFromEnum(Type enumType, System.Resources.ResourceManager mgr, string prefix = null, string[] exclude = null) { if (!enumType.IsEnum) throw new ArgumentException("Specified type is not an enumeration.", "enumType"); if (mgr == null) throw new ArgumentNullException("mgr", "A valid ResourceManager instance must be provided."); long allVal; this.checkedListBox1.BeginUpdate(); ComboBoxExtension.InitializeFromEnum(this.checkedListBox1.Items, enumType, mgr, prefix, out allVal, exclude); if (!string.IsNullOrEmpty(this.CheckAllText)) this.checkedListBox1.Items.Insert(0, new DropDownCheckListItem(this.CheckAllText, allVal)); this.checkedListBox1.EndUpdate(); } /// /// Initializes the check list from an enumerated type and sets its initial checks. /// /// Enumerated type used to set the items. /// The flag value used to check the items. /// The that holds the display text for each enumerated value. /// (Optional) The prefix used in front of the enumeration value to pull from the resource file. If null, then this value defaults to the name of the enumerated type specified by . /// (Optional) The excluded items from the enumerated type. public void InitializeAndSet(T val, System.Resources.ResourceManager mgr, string prefix = null, T[] exclude = null) where T: struct, IConvertible { EnumUtil.CheckIsEnum(true); string[] excl = exclude == null ? null : Array.ConvertAll(exclude, t => t.ToString()); this.InitializeFromEnum(typeof(T), mgr, prefix, excl); this.CheckedFlagValue = Convert.ToInt64(val); } /// /// Initializes the check list from an enumerated type defined in the TaskScheduler assembly /// /// The enumerated type. public void InitializeFromTaskEnum(Type enumType) { this.checkedListBox1.BeginUpdate(); this.checkedListBox1.Items.Clear(); long allVal = 0; Array vals = Enum.GetValues(enumType); for (int i = 0; i < vals.Length; i++) { long val = Convert.ToInt64(vals.GetValue(i)); allVal |= val; string text = TaskEnumGlobalizer.GetString(vals.GetValue(i)); this.checkedListBox1.Items.Add(new DropDownCheckListItem(text, val)); } if (!string.IsNullOrEmpty(this.CheckAllText)) this.checkedListBox1.Items.Insert(0, new DropDownCheckListItem(this.CheckAllText, allVal)); this.checkedListBox1.EndUpdate(); } /// /// Removes the specifed item from the check list. /// /// The index of the item to remove. public void RemoveItem(int index) { this.checkedListBox1.Items.RemoveAt(index); CheckedItemsChanged(); } /// /// Sets the specified item's check state. /// /// The index of the item. /// Checked if set to true; otherwise unchecked. public void SetItemChecked(int index, bool value) { if (this.GetItemChecked(index) != value) { this.checkedListBox1.SetItemChecked(index, value); CheckedItemsChanged(); } } /// /// Updates the text associated with each item of the check list. /// public void UpdateText() { bool hasCheckAll = !string.IsNullOrEmpty(CheckAllText); if (hasCheckAll && this.checkedListBox1.Items.Count == this.checkedListBox1.CheckedItems.Count) this.Text = this.CheckAllText; else { var items = new List(this.checkedListBox1.CheckedItems.Count); for (int i = 0; i < this.checkedListBox1.CheckedItems.Count; i++) { object ci = this.checkedListBox1.CheckedItems[i]; if (!hasCheckAll || ci.ToString() != this.CheckAllText) items.Add(ci.ToString()); } this.Text = string.Join(", ", items.ToArray()); } } internal void InitializeFromRange(int start, int end) { privateSet = true; this.checkedListBox1.BeginUpdate(); this.checkedListBox1.Items.Clear(); for (int i = start; i <= end; i++) this.checkedListBox1.Items.Add(new DropDownCheckListItem(i)); this.checkedListBox1.EndUpdate(); privateSet = false; } /// /// Raises the event. /// /// The instance containing the event data. protected override void OnDropDown(EventArgs args) { base.OnDropDown(args); CheckedItemsChanged(); } /// /// Raises the event. /// /// The instance containing the event data. protected override void OnDropDownClosed(EventArgs args) { base.OnDropDownClosed(args); CheckedItemsChanged(); } /// /// Raises the event. /// protected virtual void OnSelectedItemsChanged() { EventHandler h = this.SelectedItemsChanged; if (h != null) h(this, EventArgs.Empty); } private void CheckedItemsChanged() { int newHash = this.checkedListBox1.CheckedItems.OfType().GetItemHashCode(); if (lastCheckHash != newHash) { lastCheckHash = newHash; UpdateText(); OnSelectedItemsChanged(); } } void checkedListBox1_ItemCheck(object sender, ItemCheckEventArgs e) { if (!privateSet) { privateSet = true; if (e.Index == 0 && !string.IsNullOrEmpty(CheckAllText) && this.checkedListBox1.Items.Count > 1) { bool chk = e.NewValue == CheckState.Checked; if (!chk && AllowOnlyOneCheckedItem) this.SetItemChecked(1, true); for (int i = chk ? 1 : 2; i < this.checkedListBox1.Items.Count; i++) this.SetItemChecked(i, chk); } else { if (AllowOnlyOneCheckedItem) { if (e.NewValue == CheckState.Checked) { foreach (var i in this.checkedListBox1.CheckedIndices) this.SetItemChecked((int)i, false); } else e.NewValue = CheckState.Checked; } else { if (this.checkedListBox1.IsHandleCreated) this.BeginInvoke((MethodInvoker)(() => CheckedItemsChanged())); //onCheckTimer.Start(); //if (e.NewValue == CheckState.Unchecked && this.checkedListBox1.CheckedIndices.Count == 1 && this.checkedListBox1.CheckedIndices[0] == e.Index) // e.NewValue = CheckState.Checked; } } privateSet = false; } //base.PreventPopupHide = this.checkedListBox1.CheckedIndices.Count == 1 && this.checkedListBox1.CheckedIndices[0] == e.Index && e.NewValue == CheckState.Unchecked; } void onCheckTimer_Tick(object sender, EventArgs e) { onCheckTimer.Stop(); CheckedItemsChanged(); } } /// /// An item in a . /// public class DropDownCheckListItem : IComparable { /// /// Initializes a new instance of the class. /// public DropDownCheckListItem() : this(string.Empty, null) { } /// /// Initializes a new instance of the class. /// /// The value. public DropDownCheckListItem(object value) : this(value.ToString(), value) { } /// /// Initializes a new instance of the class. /// /// The text. public DropDownCheckListItem(string text) : this(text, text) { } /// /// Initializes a new instance of the class. /// /// The text. /// The value. public DropDownCheckListItem(string text, object value) { Text = text; Value = value; } /// /// Gets or sets the text. /// /// The text. public string Text { get; set; } /// /// Gets or sets the value. /// /// The value. public object Value { get; set; } /// /// Determines whether the specified is equal to this instance. /// /// The to compare with this instance. /// /// true if the specified is equal to this instance; otherwise, false. /// /// /// The parameter is null. /// public override bool Equals(object obj) { if (obj is DropDownCheckListItem) return Text == ((DropDownCheckListItem)obj).Text && Value == ((DropDownCheckListItem)obj).Value; if (obj.GetType() == Value.GetType()) return Value.Equals(obj); if (obj is string) return Text.Equals(obj); return base.Equals(obj); } /// /// Returns a hash code for this instance. /// /// /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. /// public override int GetHashCode() { return new { Text, Value }.GetHashCode(); } /// /// Returns a that represents this instance. /// /// /// A that represents this instance. /// public override string ToString() { return this.Text; } int IComparable.CompareTo(object obj) { if (obj is DropDownCheckListItem || obj is string) return Text.CompareTo(((DropDownCheckListItem)obj).Text); return 1; } } internal static class ComboBoxExtension { public static void InitializeFromEnum(System.Collections.IList list, Type enumType, System.Resources.ResourceManager mgr, string prefix, out long allVal, string[] exclude = null) { list.Clear(); allVal = 0; if (prefix == null) prefix = string.Empty; Array vals = Enum.GetValues(enumType); string[] names = Enum.GetNames(enumType); for (int i = 0; i < vals.Length; i++) { long val = Convert.ToInt64(vals.GetValue(i)); if (exclude == null || Array.IndexOf(exclude, names[i]) == -1) { allVal |= val; string text = mgr.GetString(prefix + names[i], System.Globalization.CultureInfo.CurrentUICulture); if (string.IsNullOrEmpty(text)) text = names[i]; //text = System.Threading.Thread.CurrentThread.CurrentCulture.TextInfo.ToTitleCase(text); list.Add(new DropDownCheckListItem(text, val)); } } } } }