|
/* Copyright � 2003 by Christoph Richner.\nAll rights are reserved.
*
* If you like this code then feel free to go ahead and use it.
* The only thing I ask is that you don't remove or alter my copyright notice.
* Your use of this software is entirely at your own risk. I make no claims or
* warrantees about the reliability or fitness of this code for any particular purpose.
* If you make changes or additions to this code please mark your code as being yours.
*
* If you have questions or comments then please contact me at: microweb@bluewin.ch
* */
using System;
using System.ComponentModel;
using System.Collections;
using System.Diagnostics;
using System.Windows.Forms;
using System.Drawing;
using System.Reflection;
namespace Raccoom.Windows.Forms
{
/// <summary>
/// Microsoft Internet Explorer Advanced Settings TreeView Clone.
/// <p>TreeView handles
/// <list type="bullet">
/// <item><c>checkbox</c> </item>
/// <item><c>radiobutton</c> groups</item>
/// <item>nodes to group items</item>
/// </list></p>
/// <seealso cref="TreeNodeCheckBox"/><seealso cref="TreeNodeRadioButtonGroup"/><seealso cref="TreeNodeBase"/>
/// <p>Provides a user interface for browsing the properties of an object. The public read and writeable properties of type
/// <c>bool</c> and <c>enum</c> are fetched and displayed as <c>CheckBoxes</c> and <c>RadioButtons</c>.</p>
/// <p>The fetched properties are bound to the nodes, if you change the states in the treeview your instance is updated.</p>
/// </summary>
/// <example>
/// The following example creates a new instance of a TreeViewRadioBoxReflection and set a DataGridBoolColumn as selected object.
/// <code>
/// TreeViewRadioBox treeViewRadioBox = new TreeViewRadioBox();
/// treeViewRadioBox.SelectedObject = new System.Windows.Forms.DataGridBoolColumn();
/// </code>
/// </example>
/// <remarks>The reflection only fill <c>bool</c> and <c>enum</c> types, the selected object must provide this types, otherwise don't be suprised about a empty TreeViewRadioBoxReflection.</remarks>
public class TreeViewRadioBoxReflection : TreeViewRadioBox
{
#region fields
/// <summary>Specifies the <c>Imagelist</c> index where the dynamic loaded image relies.</summary>
private int clearImageIndex_;
/// <summary>The object for which the treeview displays properties.</summary>
private object selectedObject_;
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;
#endregion
/// <summary>
/// Constructor needed for Design Time
/// </summary>
/// <param name="container"></param>
public TreeViewRadioBoxReflection(System.ComponentModel.IContainer container)
{
container.Add(this);
InitializeComponent();
}
/// <summary>
/// Standard constructor
/// </summary>
public TreeViewRadioBoxReflection()
{
InitializeComponent();
}
#region public interface
/// <summary>
/// Gets or sets the object for which the treeview displays properties.
/// </summary>
[Browsable(true), Category("Data")]
public object SelectedObject
{
get
{
return selectedObject_;
}
set
{
if(value==null) return;
//
selectedObject_ = value;
System.Collections.Hashtable categoryMap = new Hashtable();
TreeNodeBase groupNode = null;
this.Cursor = Cursors.WaitCursor;
this.BeginUpdate();
this.SuspendItemCheckedEvent(true);
try
{
this.Nodes.Clear();
foreach(PropertyInfo pi in selectedObject_ .GetType().GetProperties())
{
// check property type
if(!((pi.PropertyType.BaseType == typeof(Enum)) || (pi.PropertyType == typeof(bool)))) continue;
// must have get and set accessor's
if((!pi.CanRead) || (!pi.CanWrite)) continue;
// read Category
System.ComponentModel.CategoryAttribute[] category =(CategoryAttribute[]) pi.GetCustomAttributes(typeof(System.ComponentModel.CategoryAttribute), true);
if(category.GetLength(0)==0) category = new CategoryAttribute[] {new CategoryAttribute("Misc")};
// create/evaluate category group node
if(!categoryMap.ContainsKey(category[0].Category))
{
TreeNodeGroup node = new TreeNodeGroup(category[0].Category,this.ImageIndex, this.SelectedImageIndex);
this.Nodes.Add(node);
categoryMap.Add(category[0].Category,node);
}
groupNode = categoryMap[category[0].Category] as TreeNodeBase;
// add new radio button group node to category group node
if(pi.PropertyType.BaseType == typeof(Enum))
{
TreeNodeRadioButtonGroup node = new TreeNodeRadioButtonGroup(pi.Name,clearImageIndex_,clearImageIndex_);
groupNode.Nodes.Add(node);
node.UserData = pi;
//
foreach(string data in Enum.GetNames(pi.PropertyType))
{
TreeNodeRadioButton subnode = new TreeNodeRadioButton (data.ToString());
subnode.UserData = data;
//
node.Nodes.Add(subnode);
}
}
// add new checkbox node to category group node
else if(pi.PropertyType == typeof(bool))
{
TreeNodeCheckBox node = new TreeNodeCheckBox (pi.Name);
groupNode.Nodes.Add(node);
node.UserData = pi;
node.Checked = (bool) pi.GetValue(selectedObject_,null);
}
}
}
catch (System.Exception e)
{
System.Diagnostics.Debug.WriteLine(e.Message);
}
finally
{
this.SuspendItemCheckedEvent(false);
this.Nodes[0].EnsureVisible();
this.EndUpdate();
this.Cursor = Cursors.Default;
}
}
}
#endregion
#region internal interface
/// <summary>
/// Add the needed images to the <c>Imagelist</c> to draw <c>Checkbox</c> and <c>RadioButton</c>.
/// </summary>
protected override void AddImages()
{
Bitmap bitmap = new Bitmap(this.ImageList.ImageSize.Width, this.ImageList.ImageSize.Height);
using(System.Drawing.Graphics graphics = System.Drawing.Graphics.FromImage(bitmap))
{
graphics.FillRectangle(SystemBrushes.Window,new Rectangle(0,0,this.ImageList.ImageSize.Width, this.ImageList.ImageSize.Height));
clearImageIndex_ = this.ImageList.Images.Add(bitmap,Color.Transparent);
}
bitmap.Dispose();
//
base.AddImages();
}
#endregion
#region events
/// <summary>
/// Raise the ItemChecked event, handle databinding between properties and nodes.
/// </summary>
/// <param name="e"></param>
protected override void OnItemChecked(TreeViewEventArgs e)
{
TreeNodeBase node = e.Node as TreeNodeBase;
if((node==null) || (node.UserData==null))return;
//
PropertyInfo pi = node.UserData as PropertyInfo;
if(e.Node is TreeNodeCheckBox)
{
pi.SetValue(selectedObject_ ,node.Checked,null);
}
else if(e.Node is TreeNodeRadioButtonGroup)
{
pi.SetValue(selectedObject_ ,Enum.Parse(pi.PropertyType, ((TreeNodeRadioButtonGroup)e.Node).SelectedItemValue.ToString(),true),null);
}
//
base.OnItemChecked (e);
}
#endregion
#region Component Designer generated code
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if(components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
}
#endregion
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.