?? tristatetree.cs
字號(hào):
using System;
using System.Windows.Forms;
using System.Drawing;
using System.Runtime.InteropServices;
using System.ComponentModel;
namespace WinImageSample
{
[FlagsAttribute]
public enum CheckBoxState
{
Unchecked = 1,
Checked = 2,
Indeterminate = CheckBoxState.Unchecked | CheckBoxState.Checked
}
/// <summary>
/// ThreeStateTreeNode inherits from <see cref="http://msdn2.microsoft.com/en-us/library/sc9ba94b(vs.80).aspx">TreeView</see>
/// and adds the ability to cascade state changes to related nodes, i.e. child nodes and or parent nodes, as well as to optionally
/// use the three state functionality.
/// </summary>
public class ThreeStateTreeView : TreeView
{
ImageList _imageList;
private bool bHandleCreated = false;
#region Constructors
/// <summary>
/// Initializes a new instance of the ThreeStateTreeView class in addition to intializing
/// the base class (<see cref="http://msdn2.microsoft.com/en-us/library/system.windows.forms.treeview.treeview(VS.80).aspx">TreeView Constructor</see>).
/// </summary>
public ThreeStateTreeView()
: base()
{
InitializeComponent();
base.CheckBoxes = true;
_imageList = new ImageList();
_imageList.ImageSize = new Size(16, 16);
if (!NativeMethods.VisualStylesEnabled()) { _imageList = ilChecks; }
else
{
_imageList.Images.Add(ilChecks.Images["Checked0"]);
UXTheme.LoadCheckBoxImage(_imageList, UXTheme.CheckBoxState.UncheckedNormal);
UXTheme.LoadCheckBoxImage(_imageList, UXTheme.CheckBoxState.CheckedNormal);
UXTheme.LoadCheckBoxImage(_imageList, UXTheme.CheckBoxState.MixedNormal);
}
}
#endregion
private ImageList ilChecks;
private IContainer components;
#region Public Properties
/// <summary>
/// Flag. If true, use three state checkboxes, otherwise, use the default behavior of the TreeView and associated TreeNodes.
/// </summary>
private bool mUseThreeStateCheckBoxes = true;
[Category("Three State TreeView"),
Description("Flag. If true, use three state checkboxes, otherwise, use the default behavior of the TreeView and associated TreeNodes."),
DefaultValue(true),
TypeConverter(typeof(bool)),
Editor("System.Boolean", typeof(bool))]
public bool UseThreeStateCheckBoxes
{
get { return this.mUseThreeStateCheckBoxes; }
set { this.mUseThreeStateCheckBoxes = value; }
}
#endregion
#region Overrides
public new ImageList ImageList
{
get { return base.ImageList; }
set
{
base.ImageList = value;
this.SetCheckImageList();
}
}
/// <summary>
/// Raises the AfterCheck event.
/// </summary>
/// <param name="e">A <see cref="http://msdn2.microsoft.com/en-us/library/system.windows.forms.treevieweventargs.aspx">TreeViewEventArgs</see> containing the event data.</param>
protected override void OnAfterCheck(TreeViewEventArgs e)
{
if (this.UseThreeStateCheckBoxes)
{
switch (e.Action)
{
case TreeViewAction.ByKeyboard:
case TreeViewAction.ByMouse:
{
if (e.Node is ThreeStateTreeNode)
{
// Toggle to the next state.
ThreeStateTreeNode tn = e.Node as ThreeStateTreeNode;
tn.Toggle();
}
break;
}
case TreeViewAction.Collapse:
case TreeViewAction.Expand:
case TreeViewAction.Unknown:
default:
{
// Do nothing.
break;
}
}
}
base.OnAfterCheck(e);
}
protected override void OnHandleCreated(EventArgs e)
{
base.OnHandleCreated(e);
bHandleCreated = true;
SetCheckImageList();
}
#endregion
#region Hide no longer appropriate properties from Designer
[Browsable(false)]
public new bool CheckBoxes
{
get { return base.CheckBoxes; }
internal set { base.CheckBoxes = value; }
}
[Browsable(false)]
public new int ImageIndex
{
get { return base.ImageIndex; }
set { base.ImageIndex = value; }
}
[Browsable(false)]
public new int SelectedImageIndex
{
get { return base.SelectedImageIndex; }
set { base.SelectedImageIndex = value; }
}
[Browsable(false)]
public new ImageList StateImageList
{
get { return base.StateImageList; }
internal set { base.StateImageList = value; }
}
#endregion
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ThreeStateTreeView));
this.ilChecks = new System.Windows.Forms.ImageList(this.components);
this.SuspendLayout();
//
// ilChecks
//
this.ilChecks.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("ilChecks.ImageStream")));
this.ilChecks.TransparentColor = System.Drawing.Color.Transparent;
this.ilChecks.Images.SetKeyName(0, "Checked0");
this.ilChecks.Images.SetKeyName(1, "Checked1");
this.ilChecks.Images.SetKeyName(2, "Checked2");
this.ilChecks.Images.SetKeyName(3, "Checked3");
this.ResumeLayout(false);
}
private void SetCheckImageList()
{
if (!bHandleCreated) return;
NativeMethods.SendMessage(
new HandleRef(this, this.Handle),
(int)NativeMethods.Messages.TVM_SETIMAGELIST,
(int)NativeMethods.TreeViewImageListType.TVSIL_STATE,
(int)_imageList.Handle);
}
}
/// <summary>
/// ThreeStateTreeNode inherits from <see cref="http://msdn2.microsoft.com/en-us/library/system.windows.forms.treenode.aspx">TreeNode</see>
/// and adds the ability to support a third, indeterminate state as well as optionally cascading state changes to related nodes, i.e.
/// child nodes and or parent nodes, as determined by this instance's related parent TreeView settings, CascadeNodeChecksToChildNodes and
/// CascadeNodeChecksToParentNode.
/// </summary>
public class ThreeStateTreeNode : TreeNode
{
#region Constructors
/// <summary>
/// Initializes a new instance of the ThreeStateTreeNode class in addition to intializing
/// the base class (<see cref="http://msdn2.microsoft.com/en-us/library/bk8h64c9.aspx">TreeNode Constructor</see>).
/// </summary>
public ThreeStateTreeNode()
: base()
{
this.CommonConstructor();
}
/// <summary>
/// Initializes a new instance of the ThreeStateTreeNode class with a string for the text label to display in addition to intializing
/// the base class (<see cref="http://msdn2.microsoft.com/en-us/library/ytx906df.aspx">TreeNode Constructor</see>).
/// </summary>
/// <param name="text">The string for the label of the new tree node.</param>
public ThreeStateTreeNode(string text)
: base(text)
{
this.CommonConstructor();
}
/// <summary>
/// Initializes a new instance of the ThreeStateTreeNode class with a string for the text label to display
/// and an array of child ThreeStateTreeNodes in addition to intializing the base class
/// (<see cref="http://msdn2.microsoft.com/en-us/library/774ty506.aspx">TreeNode Constructor</see>).
/// </summary>
/// <param name="text">The string for the label of the new tree node.</param>
/// <param name="children">An array of child ThreeStateTreeNodes.</param>
public ThreeStateTreeNode(string text, ThreeStateTreeNode[] children)
: base(text, children)
{
this.CommonConstructor();
}
/// <summary>
/// Initializes a new instance of the ThreeStateTreeNode class with a string for the text label to display
/// and the selected and unselected image indexes in addition to intializing the base class
/// (<see cref="http://msdn2.microsoft.com/en-us/library/8dfy3k5t.aspx">TreeNode Constructor</see>).
/// </summary>
/// <param name="text">The string for the label of the new tree node.</param>
/// <param name="imageIndex">The image index of the unselected image in the parent TreeView's <see cref="http://msdn2.microsoft.com/en-us/library/system.windows.forms.treeview.imagelist.aspx">ImageList</see>.</param>
/// <param name="selectedImageIndex">The image index of the selected image in the parent TreeView's <see cref="http://msdn2.microsoft.com/en-us/library/system.windows.forms.treeview.imagelist.aspx">ImageList</see>.</param>
public ThreeStateTreeNode(string text, int imageIndex, int selectedImageIndex)
: base(text, imageIndex, selectedImageIndex)
{
this.CommonConstructor();
}
/// <summary>
/// Initializes a new instance of the ThreeStateTreeNode class with a string for the text label to display ,
/// the selected and unselected image indexes, and an array of child ThreeStateTreeNodes in addition to intializing the base class
/// (<see cref="http://msdn2.microsoft.com/en-us/library/8dfy3k5t.aspx">TreeNode Constructor</see>).
/// </summary>
/// <param name="text">The string for the label of the new tree node.</param>
/// <param name="imageIndex">The image index of the unselected image in the parent TreeView's <see cref="http://msdn2.microsoft.com/en-us/library/system.windows.forms.treeview.imagelist.aspx">ImageList</see>.</param>
/// <param name="selectedImageIndex">The image index of the selected image in the parent TreeView's <see cref="http://msdn2.microsoft.com/en-us/library/system.windows.forms.treeview.imagelist.aspx">ImageList</see>.</param>
/// <param name="children">An array of child ThreeStateTreeNodes.</param>
public ThreeStateTreeNode(string text, int imageIndex, int selectedImageIndex, ThreeStateTreeNode[] children)
: base(text, imageIndex, selectedImageIndex, children)
{
this.CommonConstructor();
}
#endregion
#region Initialization
/// <summary>
/// Performs common initialization to all constructors.
/// </summary>
private void CommonConstructor()
{
}
#endregion
#region Properties
/// <summary>
/// The current state of the checkbox.
/// </summary>
private CheckBoxState mState = CheckBoxState.Unchecked;
[Category("Three State TreeView"),
Description("The current state of the node's checkbox, Unchecked, Checked, or Indeterminate"),
DefaultValue(CheckBoxState.Unchecked),
TypeConverter(typeof(CheckBoxState)),
Editor("Ascentium.Research.Windows.Components.CheckBoxState", typeof(CheckBoxState))]
public CheckBoxState State
{
get { return this.mState; }
set
{
if (this.mState != value)
{
this.mState = value;
// Ensure if checkboxes are used to make the checkbox checked or unchecked.
// When go to a fully drawn control, this will be managed in the drawing code.
// Setting the Checked property in code will cause the OnAfterCheck to be called
// and the action will be 'Unknown'; do not handle that case.
//if ((this.TreeView != null) && (this.TreeView.CheckBoxes))
// this.Checked = (this.mState == CheckBoxState.Checked);
SetState(value);
}
}
}
/// <summary>
/// Returns the 'combined' state for all siblings of a node.
/// </summary>
private CheckBoxState SiblingsState
{
get
{
// If parent is null, cannot have any siblings or if the parent
// has only one child (i.e. this node) then return the state of this
// instance as the state.
if ((this.Parent == null) || (this.Parent.Nodes.Count == 1))
return this.State;
// The parent has more than one child. Walk through parent's child
// nodes to determine the state of all this node's siblings,
// including this node.
CheckBoxState state = 0;
foreach (TreeNode node in this.Parent.Nodes)
{
ThreeStateTreeNode child = node as ThreeStateTreeNode;
if (child != null)
state |= child.State;
// If the state is now indeterminate then know there
// is a combination of checked and unchecked nodes
// and no longer need to continue evaluating the rest
// of the sibling nodes.
if (state == CheckBoxState.Indeterminate)
break;
}
return (state == 0) ? CheckBoxState.Unchecked : state;
}
}
#endregion
#region Methods
/// <summary>
/// Manages state changes from one state to the next.
/// </summary>
/// <param name="fromState">The state upon which to base the state change.</param>
public void Toggle(CheckBoxState fromState)
{
switch (fromState)
{
case CheckBoxState.Indeterminate:
case CheckBoxState.Unchecked:
{
this.State = CheckBoxState.Checked;
break;
}
case CheckBoxState.Checked:
default:
{
this.State = CheckBoxState.Unchecked;
break;
}
}
this.UpdateStateOfRelatedNodes();
}
/// <summary>
/// Manages state changes from one state to the next.
/// </summary>
public new void Toggle() { this.Toggle(this.State); }
/// <summary>
/// Manages updating related child and parent nodes of this instance.
/// </summary>
public void UpdateStateOfRelatedNodes()
{
ThreeStateTreeView tv = this.TreeView as ThreeStateTreeView;
if ((tv != null) && tv.CheckBoxes && tv.UseThreeStateCheckBoxes)
{
tv.BeginUpdate();
// If want to cascade checkbox state changes to child nodes of this node and
// if the current state is not intermediate, update the state of child nodes.
if (this.State != CheckBoxState.Indeterminate)
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -