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 DropDownCheckTree : CustomComboBox
{
private List checkedItems = new List();
private System.Windows.Forms.TreeView checkedTreeView;
private bool updatingChecks;
private Dictionary values = new Dictionary();
///
/// Initializes a new instance of the class.
///
public DropDownCheckTree()
{
this.checkedTreeView = new System.Windows.Forms.TreeView()
{
BorderStyle = System.Windows.Forms.BorderStyle.None,
CheckBoxes = true,
Name = "checkedTreeView",
ShowLines = true,
ShowPlusMinus = true,
Tag = this,
Visible = false
};
this.checkedTreeView.AfterCheck += checkedTreeView_ItemCheck;
base.DropDownControl = this.checkedTreeView;
base.DropSize = new System.Drawing.Size(base.DropDownWidth, 400);
}
private delegate void NodeAction(TreeNode node, bool childrenChecked);
///
/// Occurs when the property changes.
///
[Category("Action"), Description("Occurs when the SelectedItems property changes.")]
public event EventHandler SelectedItemsChanged;
///
/// 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 the checked items.
///
/// The checked items.
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public List CheckedItems
{
get { return this.checkedItems; }
}
///
/// 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 TreeNodeCollection Items
{
get { return this.checkedTreeView.Nodes; }
}
///
/// 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.checkedTreeView.Sorted; }
set { this.checkedTreeView.Sorted = value; }
}
///
/// Checks the matching items.
///
/// The match.
/// if set to true keep existing checked items.
public void CheckItems(Predicate match, bool keepExisting = false)
{
ForEachChildNode(this.checkedTreeView.Nodes, n => { if (match == null || match(n.Name)) n.Checked = true; else if (!keepExisting) n.Checked = false; });
UpdateText();
}
///
/// Checks the item in the tree whose value matches the one specified by .
///
/// The value to match.
/// if set to true check the matching item, else uncheck it.
public void CheckValue(string value, bool check = true)
{
TreeNode node;
if (value != null && value is string)
if (values.TryGetValue((string)value, out node))
node.Checked = check;
UpdateText();
}
///
/// Unchecks all items in the tree.
///
public void UncheckAllItems()
{
updatingChecks = true;
for (int i = checkedItems.Count - 1; i >= 0; i--)
checkedItems[i].Checked = false;
checkedItems.Clear();
updatingChecks = false;
UpdateText();
}
///
/// Updates the text associated with each item of the check list.
///
public void UpdateText()
{
if (this.checkedItems.Count == 0)
{
this.Text = string.Empty;
}
else
{
if (this.checkedItems.Count == this.checkedTreeView.GetNodeCount(true) && this.CheckAllText != null)
this.Text = this.CheckAllText;
else
{
var selNodes = this.checkedItems.FindAll(n => !string.IsNullOrEmpty(n.Name)).ConvertAll(t => (string)t.Name);
selNodes.Sort();
this.Text = string.Join(", ", selNodes.ToArray());
}
}
}
internal static TreeNode AddValue(TreeNodeCollection nodeColl, string text, string key)
{
TreeNode child = nodeColl.Add(key, text);
if (key != null)
{
if (child.TreeView != null && child.TreeView.Parent != null && child.TreeView.Tag is DropDownCheckTree)
((DropDownCheckTree)child.TreeView.Tag).values.Add(key, child);
}
return child;
}
///
/// Raises the event.
///
/// An that contains the event data.
protected override void OnDropDownClosed(EventArgs e)
{
base.OnDropDownClosed(e);
UpdateText();
}
///
/// Raises the event.
///
protected virtual void OnSelectedItemsChanged()
{
EventHandler h = this.SelectedItemsChanged;
if (h != null)
h(this, EventArgs.Empty);
}
private bool AreChildrenChecked(TreeNode treeNode, NodeAction nodeAction = null)
{
bool foundCheck = false;
foreach (TreeNode n in treeNode.Nodes)
{
if (n.Checked || AreChildrenChecked(n))
{
foundCheck = true;
break;
}
}
if (nodeAction != null)
nodeAction(treeNode, foundCheck);
return foundCheck;
}
private void checkedTreeView_ItemCheck(object sender, TreeViewEventArgs e)
{
// Update checked items list
if (e.Node.Checked)
this.checkedItems.Add(e.Node);
else
this.checkedItems.Remove(e.Node);
// Update parent and children checks appropriately
if (!updatingChecks)
{
updatingChecks = true;
SetCheckOnChildren(e.Node);
TreeNode n = e.Node;
while (n.Parent != null)
{
n.Parent.Checked = e.Node.Checked ? true : AreChildrenChecked(n.Parent);
n = n.Parent;
}
OnSelectedItemsChanged();
updatingChecks = false;
}
}
private void ForEachChildNode(TreeNodeCollection pNodes, Action action, bool allChildren = true)
{
foreach (TreeNode node in pNodes)
{
action(node);
if (allChildren)
ForEachChildNode(node.Nodes, action, allChildren);
}
}
private void SetCheckOnChildren(TreeNode treeNode)
{
bool pChecked = treeNode.Checked;
ForEachChildNode(treeNode.Nodes, n => { n.Checked = pChecked; });
}
}
}