using System; using System.Collections.Generic; using System.Text; using System.Drawing; using System.Resources; using System.ComponentModel; using System.Windows.Forms; namespace CustomControls { /// <summary> /// 涂聚文 2014-06-30 修改 /// DropDownTreeView class offers TreeView that is desined to act under a drop down control /// You can use this control when you need to select a value from a dynamic TreeView. /// The sub controls of this control are set to protected. You can override the control /// to assign values to the subcontrol of change their behaviour. /// http://www.codeproject.com/Articles/3994/Custom-ComboBoxes-with-Advanced-Drop-down-Features /// </summary> public class DropDownComboxTreeView : UserControl { /// <summary> /// protected Button control, this is the control's toggle button /// </summary> protected ButtonEx btnSelect; /// <summary> /// protected TextBox control, this is control's value TextBox. /// The TextBox's ReadyOnly false is by default set ti true /// </summary> protected ComboBox useComboxBox; /// <summary> /// protected TreeView control, this is the control's TreeView. /// </summary> protected TreeView treeView; /// <summary> /// protected value that is set to true of false within the /// SetTextValueToSelectedNode method. /// </summary> protected bool TextValueSet=false; /// <summary> /// the resize label on the Control's TreeView control /// </summary> private LabelEx treeLabel; /// <summary> /// This is the margin in pixels for resizing the TreeView /// </summary> private int Margin = 10; /// <summary> /// TreeView's minimum width /// </summary> private int tvMinWidth = 0; /// <summary> /// TreeView's minimum height /// </summary> private int tvMinHeight = 150; //private ComboBox.ObjectCollection itm; /// <summary> /// General point to access MouseMove event for resizing the TreeView /// </summary> private MouseEventArgs parentMouse; // ComboboxItem item = null; //private string _Text; // public string ComboxText // { // get { return _Text; } // set { _Text = value; } // } //private string _Value; // public string ComboxValue // { // get { return _Value; } // set { _Value = value; } // } /// <summary> /// Get TreeNodeCollection collection, Herewith you can add and remove items to the treeview /// </summary> [ Description("Gets the TreeView Nodes collection"), Category("TreeView") ] public TreeNodeCollection Nodes { get { return treeView.Nodes; } } /// <summary> /// Get,set property that provides the TreeView's Selected Node /// </summary> [ Description("Gets or sets the TreeView's Selected Node"), Category("TreeView") ] public TreeNode SelectedNode { get { return treeView.SelectedNode; } set { treeView.SelectedNode = value; } } /// <summary> /// Get, set property of boolean type, this property is mapped to the ReadOnly property of the control's TextBox /// </summary> [ Description("Gets or sets the ComboBox's Enabled state"), Category("ComboBox") ] public bool ComboBoxReadOnly { set { useComboxBox.Enabled = value; } get { return useComboxBox.Enabled; } } //[ // Description("Gets or sets the ComboBox's text state"), // Category("ComboBox") //] //public ComboboxItem Items //{ // get // { // return object; //txtValue.Items // } // set // { // txtValue.SelectedItem = value; // } //} /// <summary> /// /// </summary> //public List<UserCombox> //{ // List<UserCombox> collection=new List<UserCombox>; //} //public UserCombox Items //{ // get { } // set { } //} //[ // Description("Gets or sets the ComboBox's text state"), // Category("ComboBox") //] public ComboBox.ObjectCollection Items { //ComboBox.ObjectCollection items= new ComboBox.ObjectCollection(txtValue); set { for (int i = 0; i < value.Count; i++) { useComboxBox.Items.Add(value[i]); } } get { //if (Items.Count > 0) //{ // txtValue.Items.Add(Items); //} return this.useComboxBox.Items; } } [ Description("Gets the ComboxBox DataSource"), Category("ComboBox") ] public Object DataSource { set { useComboxBox.DataSource = value; //要先的关系 } get { return useComboxBox.DataSource; } } [ Description("Gets the ComboxBox DataSource DisplayMember"), Category("ComboBox") ] public string DisplayMember { set { useComboxBox.DisplayMember = value; } get { return useComboxBox.DisplayMember; } } [ Description("Gets the ComboxBox DataSource ValueMember"), Category("ComboBox") ] public string ValueMember { set { useComboxBox.ValueMember = value; } get { return useComboxBox.ValueMember; } } // public static void SetLookupBinding(ListControl toBind, //object dataSource, string displayMember, //string valueMember) // { // toBind.DisplayMember = displayMember; // toBind.ValueMember = valueMember; // // Only after the following line will the listbox // // receive events due to binding. // toBind.DataSource = dataSource; // } /// <summary> /// Get, set property thai is mapped to the Control's treeView control's ImageList property. /// </summary> public ImageList Imagelist { get { return treeView.ImageList; } set { treeView.ImageList = value; } } /// <summary> /// Control's constuctor /// </summary> public DropDownComboxTreeView() { //item=new ComboboxItem(); //item.Text = "";// CustomControls.CustComboboxItem.ComboxText; //item.Value = "";// CustomControls.CustComboboxItem.ComboxValue; // General TextValueSet = false; // Initializing Controls InitControls(); // Setting The locations SetSizeAndLocation(); // Adding Controls to UserControl this.Controls.AddRange(new Control[] { btnSelect, useComboxBox, treeView }); // attaching events this.Resize += new EventHandler(ControlResize); this.LocationChanged += new EventHandler(ControlResize); } /// <summary> /// Control's resize handler, this handler is attached to the controls Resize and LocationChanged events /// </summary> /// <param name="sender">sender obcject</param> /// <param name="e">default EventArgs</param> private void ControlResize(object sender, EventArgs e) { // Setting The locations SetSizeAndLocation(); } /// <summary> /// Controls, sub control initializer, private void that handles the control initialization. /// </summary> public void InitControls() { try { //value box settings; useComboxBox = new ComboBox(); this.ComboBoxReadOnly = true; useComboxBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.Simple; //初始化的值 //if (TextValueSet == false) //{ // ComboboxItem item = new ComboboxItem(); // ////txtValue.Text = this.SelectedNode.Text; //设定的值 // item.Text = CustComboboxItem.ComboxText; // item.Value = CustComboboxItem.ComboxValue; //if (!object.Equals(item, null)) //{ // txtValue.Items.Add(item); // txtValue.SelectedIndex = 0; //} //} //txtValue.Text = "gee"; //txtValue.Text = ""; //txtValue.Items.Add(SelecItem); if (TextValueSet == false) { useComboxBox.DataSource = DataSource; useComboxBox.DisplayMember = DisplayMember; useComboxBox.ValueMember = ValueMember; } else { useComboxBox.DataSource = null; } useComboxBox.Size = new System.Drawing.Size(121, 18); //select button settings btnSelect = new ButtonEx(); //btnSelect.Font = new Font("System",7); //btnSelect.Text = "+"; //btnSelect.TextAlign = ContentAlignment.MiddleCenter; //btnSelect.ClientSize = btnSelect.Size; btnSelect.Click += new EventHandler(ToggleTreeView); //btnSelect.Size = new Size(120,txtValue.Height); treeView = new TreeView(); treeView.BorderStyle = BorderStyle.FixedSingle; treeView.Visible = false; treeView.AfterSelect += new TreeViewEventHandler(TreeViewNodeSelect); treeView.DoubleClick += new EventHandler(TreeViewNodeDoubleClickSelect); //双击为选择 treeView.MouseMove += new MouseEventHandler(TreeViewMouseMoveEventHandler); treeView.Size = new Size(tvMinWidth, tvMinHeight); treeLabel = new LabelEx(); treeLabel.Size = new Size(16, 16); treeLabel.BackColor = Color.Transparent; treeView.Controls.Add(treeLabel); SetHotSpot(); this.SetStyle(ControlStyles.DoubleBuffer, true); this.SetStyle(ControlStyles.ResizeRedraw, true); } catch (Exception ex) { ex.Message.ToString(); } } /// <summary> /// private void for setting the HotSpot helper label. /// </summary> private void SetHotSpot() { treeLabel.Top = treeView.Height - treeLabel.Height; treeLabel.Left = treeView.Width - treeLabel.Width; } /// <summary> /// TreeView node select handler, this is a protected event method /// that is attached to the TreeView's AfterSelect event. It sets the /// TextBox's Text property. By default It checks the selected treenode, /// If the treenode dosn't have any child node then, this node's value /// is assigned to the TextBox's Text Property. /// You can implement your own AfterSelect handler by overriding this method. /// </summary> /// <param name="sender">sender object</param> /// <param name="e">default TreeViewEventArgs</param> protected void TreeViewNodeSelect(object sender, TreeViewEventArgs e) { // chiching for none root node if (this.SelectedNode.Nodes.Count == 0) //选择确定 { SetTextValueToSelectedNode(); TextValueSet = true; } } /// <summary> /// This event method is the control's TreeView's DoubleClick event handler. /// It is meant to close the TreeView when an item is DoubleClicked. /// This function calls the TreeViewNodeSelect event handler method, then if /// the TextValueSet is set to true it toggles (closes) the TreeView /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void TreeViewNodeDoubleClickSelect(object sender, EventArgs e) { this.TreeViewNodeSelect(sender, null); if (TextValueSet) { this.ToggleTreeView(sender, null); } } /// <summary> /// private void setting the control's TextBox's Text property. /// This method also sets the TextValueSet to true if a value /// is assigned to the TextBox's Text property /// </summary> private void SetTextValueToSelectedNode() { try { //useComboxBox.Items.Clear(); useComboxBox.DataSource = null; ComboboxItem item = new ComboboxItem(); //txtValue.Text = this.SelectedNode.Text; //设定的值 item.Text = this.SelectedNode.Text; item.Value = this.SelectedNode.Name; useComboxBox.Items.Clear(); useComboxBox.Items.Add(item); useComboxBox.SelectedIndex = 0; TextValueSet = true; } catch(Exception ex) { ex.Message.ToString(); TextValueSet = false; } } /// <summary> /// private event method, this method is attached to the control's Button's Clcick event. /// It handles the show/hide of the control's treeview /// </summary> /// <param name="sender">sender object</param> /// <param name="e">default EventArgs</param> private void ToggleTreeView(object sender, EventArgs e) { if (!treeView.Visible) { SetTreeViewSizeAndLocation(); try { this.btnSelect.Text = "-"; this.Parent.Controls.Add(treeView); this.treeView.BringToFront(); treeView.Visible = true; treeView.Select(); Parent.MouseMove += new MouseEventHandler(ParentMouseMoveHandler); if (treeView.Width < this.Width || treeView.Height < this.Height) { treeView.Width = tvMinWidth; treeView.Height = 150; SetHotSpot(); } } catch { } } else { try { btnSelect.Text = "+"; treeView.Visible = false; this.Parent.Controls.Remove(treeView); Parent.MouseMove -= new MouseEventHandler(ParentMouseMoveHandler); } catch { } } } /// <summary> /// /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void TreeViewMouseMoveEventHandler(object sender, MouseEventArgs e) { this.parentMouse = e; SetCursor(Cursors.Default); } /// <summary> /// /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void ParentMouseMoveHandler(object sender, MouseEventArgs e) { int tx, ty; this.parentMouse = e; tx = treeView.Left + treeView.Width; ty = treeView.Top + treeView.Height; SetHotSpot(); if (e.Button == MouseButtons.Left) { Margin = 50; treeLabel.BringToFront(); } else { Margin = 4; } if ((is_in_range(e.Y, ty - Margin, ty + Margin)) && is_in_range(e.X, tx - Margin, tx + Margin)) { SetCursor(Cursors.SizeNWSE); if (e.Button == MouseButtons.Left) { treeView.Height = e.Y - treeView.Top; treeView.Width = e.X - treeView.Left; } } else { SetCursor(Cursors.Default); } } /// <summary> /// /// </summary> /// <param name="crs"></param> private void SetCursor(Cursor crs) { treeView.Cursor = crs; Parent.Cursor = crs; } /// <summary> /// /// </summary> /// <param name="rvalue"></param> /// <param name="start"></param> /// <param name="end"></param> /// <returns></returns> private bool is_in_range(int rvalue, int start, int end) { if ((rvalue >= start) && (rvalue <= end)) { return true; } else { return false; } } /// <summary> /// /// </summary> public void SetTreeViewMinimumSize() { if ((treeView.Width < this.Width) || (treeView.Height < 150)) { treeView.Width = this.Width; treeView.Height = 150; } } /// <summary> /// private method sets the control's TreeView's size and location. /// It is called when the control is resized to moved from it's place /// </summary> private void SetTreeViewSizeAndLocation() { if (treeView != null) { treeView.Location = new Point(this.Left, this.Top + this.Height + 1); } } /// <summary> /// private method, sets the controls size and location. /// It sets the control's and sub control's sizes and locations /// </summary> private void SetSizeAndLocation() { tvMinWidth = this.Width; if (useComboxBox != null && btnSelect != null) { btnSelect.Size = new Size(useComboxBox.Height, 18); useComboxBox.Width = this.Width - btnSelect.Width - 4; useComboxBox.Location = new Point(0, 0); btnSelect.Left = useComboxBox.Width + 4; SetTreeViewSizeAndLocation(); this.Height = useComboxBox.Height; } } } /// <summary> /// Extended Label control with user paint. /// </summary> public class LabelEx : Label { /// <summary> /// /// </summary> public LabelEx() { this.SetStyle(ControlStyles.UserPaint, true); this.SetStyle(ControlStyles.DoubleBuffer, true); this.SetStyle(ControlStyles.AllPaintingInWmPaint, true); } /// <summary> /// /// </summary> /// <param name="e"></param> protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); System.Windows.Forms.ControlPaint.DrawSizeGrip(e.Graphics, Color.Black, 0, 0, 16, 16); } } /// <summary> /// /// </summary> public class ComboboxItem { string _Text; public string Text { get { return _Text; } set { _Text = value; } } object _Value; public object Value { get { return _Value; } set { _Value = value; } } public override string ToString() { return Text; } } /// <summary> /// /// </summary> public class CustComboboxItem { public static string ComboxText; public static string ComboxValue; } //private string _Text; // public string ComboxText // { // get { return _Text; } // set { _Text = value; } // } //private string _Value; // public string ComboxValue // { // get { return _Value; } // set { _Value = value; } // } /// <summary> /// Extended button control with userpaint /// </summary> public class ButtonEx : Button { ButtonState state; /// <summary> /// /// </summary> public ButtonEx() { this.SetStyle(ControlStyles.UserPaint, true); this.SetStyle(ControlStyles.DoubleBuffer, true); this.SetStyle(ControlStyles.AllPaintingInWmPaint, true); } /// <summary> /// /// </summary> /// <param name="e"></param> protected override void OnMouseDown(MouseEventArgs e) { state = ButtonState.Pushed; base.OnMouseDown(e); } /// <summary> /// /// </summary> /// <param name="e"></param> protected override void OnMouseUp(MouseEventArgs e) { state = ButtonState.Normal; base.OnMouseUp(e); } /// <summary> /// /// </summary> /// <param name="e"></param> protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); System.Windows.Forms.ControlPaint.DrawComboButton(e.Graphics, 0, 0, this.Width, this.Height, state); } } }