From time to time, it’s a good idea to go back and re-examine old code. With time comes greater knowledge and new tricks; and in the case of two of my earlier custom Windows Forms controls, this was certainly true. You may remember my ComboBox control with grouping support, as well as my ComboBox with a TreeView drop-down – I have revisited these controls, with particular mind to implementing what I learnt from my experience with the Buffered Paint API.
GroupedComboBox
To refresh your memory, this control extends ComboBox and adds a new property; GroupMember. Using PropertyDescriptor and owner-drawing, it groups together items whose grouping values are equal.
What’s new:
- On Windows Vista and 7, the control did not appear in the ‘button style’ consistent with normal ComboBox controls in DropDownList mode; this is a limitation of owner-drawing, but one that can be overcome through the use of VisualStyleRenderer. This is a slightly dodgy hack in that it pre-supposes the appearance of the ComboBox in this mode, but the functionality is only applied when the OS is identified as Vista or 7.
- The control is inconsistent with other ComboBox controls because it is not animated. With the BufferedPainter<T> class I developed, implementing buffered animation was simple.
ComboTreeBox
The ComboTreeBox is a control developed entirely from scratch (i.e. its base class is Control) that uses a hierarchical/tree structure as its data representation (instead of a flat list). As such, it has behaviours in common with both ComboBox and TreeView. The drop-down/pop-up portion of the control is implemented using ToolStripDropDown, bitmap caching and custom rendering.
What’s new:
- As with GroupedComboBox, the control did not appear in the Windows Vista/7 style. As the control has no editable portion and is entirely owner-drawn, it was easy to simulate the appearance under the appropriate OS. Under XP, it falls back to the default visual style. When themes are disabled, it draws in the classic style.
- The control was not animated. Once again, BufferedPainter<T> was used to implement animation.
- Due to a strongly-typed reference to its designer class, the control previously did not work with the “Client Profile” version of the .NET Framework. Rather cheekily, I have substituted my custom designer for the built-in designer that the DomainUpDown control uses – this works well for constraining the height of the control and avoids the need to reference the System.Design assembly (included only with the full version of the framework).
- Minor tweaks were made to the way focused items are drawn; this is only apparent if focus cues are enabled in Windows.
Download
Please visit the project page here: Drop-Down Controls
public VisualStateTrigger(VisualStateTriggerTypes type, TState state, Rectangle bounds = default(Rectangle), AnchorStyles anchor = AnchorStyles.Top | AnchorStyles.Left)
{
Type = type;
State = state;
Bounds = bounds;
Anchor = anchor;
}
give an error ……..Error 4 Default parameter specifiers are not permitted
Akber: You need to build using the C# 4.0 compiler (Visual Studio 2010); default parameters have been allowed in C# for some time now.
Alternatively, you can add some overloaded methods to simulate the effect of having default parameters:
public VisualStateTrigger(VisualStateTriggerTypes type, TState state, Rectangle bounds) : this(type, state, bounds, AnchorStyles.Top | AnchorStyles.Left) { }
public VisualStateTrigger(VisualStateTriggerTypes type, TState state) : this(type, state, default(Rectangle), AnchorStyles.Top | AnchorStyles.Left) { }
I tried by adding the above 2 overloads…and still i was getting error so i changed this function as :
public VisualStateTrigger(VisualStateTriggerTypes type, TState state, Rectangle bounds = default(Rectangle), AnchorStyles anchor = AnchorStyles.Top | AnchorStyles.Left) {
Type = type;
State = state;
Bounds = bounds;
Anchor = anchor;
}
public VisualStateTrigger(VisualStateTriggerTypes type, TState state, Rectangle bounds , AnchorStyles anchor ) {
Type = type;
State = state;
Bounds = bounds;
Anchor = anchor;
}
but now its making dll …but when drag and drop it doesnt draw a combotreebox..can you please tell what wrong im doing?
groupbox works but combotreebox doesnt work plz help…i have already used ur control n now this erroor coming ..i cnnot do anything else bcoz this project is at the last stage and i cannot change it…
Pingback: A ComboBox Control With Grouping | Brad Smith's Coding Blog
Hi, how can I use ComboTreeDropDown in asp.net website,in aspx page? Can u help? Thank u
It is a Windows Forms control – it cannot be used in ASP.NET.
GroupedComboBox 2 issues
1. Have dupicated group, seems not grouping very well; For exmaple:
Fruit
A
B
Fruit
C
2. The DropDownList Items showing overlapped on screen, seems the height is not adjusted very well. Only the last item of each group showing full height, even group item showing partially.
I’m not able to reproduce either of your two problems. Please post your code.
its working fine.. but there is one problem.. horizontal scroll bar is not available in this control
If your drop-down contains content that requires a horizontal scroll bar, you should consider using a more appropriate type of control.
Hi Bradley
Thanx a lot for your work. It really improves my solution. Great.
Nice components. Give you LIKE!
Hello, thanks a lot for your control. I am using this control and is excelent. Congratulations.
I’d like to add to the control the property ReadOnly. (For What? I want to disabled the control but I am not want to use enabled=false because it changes the color). Can you give me a clue? I work with Visual Basic and I can not find where make the change in the C# code.
Thanks
Hi Manuel,
I chose not to implement a ReadOnly property on my controls because the built-in ComboBox control (which they are based on) does not implement such a property either. The purpose of read-only mode on the TextBox control is to allow text to be selected and scrolled while still preventing user input – for the ComboTreeBox control, there is no editable portion, so this property cannot apply. For the GroupedComboBox control, read-only mode would only affect the control in Simple or DropDown modes.
If you still wanted to implement this property, it would be complex; you would have to disable the dropdown behaviour in response to the mouse/keyboard events (with the ComboBox control, this is difficult because the control handles input using a native method instead of a managed one). Visually, however, it would be relatively simple; simply render the controls in the normal way if the ReadOnly property is set to true – although I think the background is usually filled with a different colour, so you would have to account for that.
Personally, I do not think it is worth attempting this; it is not consistent with other Windows Forms controls of the same type.
Great control, well done, Just one issue, when I Enabled = false, the combo doesn’t draw disabled like a normal combo.
Thanks for pointing this out. There’s an easy fix – in DropDownControlBase.cs, add the following method:
protected override void OnEnabledChanged(EventArgs e) {
base.OnEnabledChanged(e);
_bufferedPainter.State = GetComboBoxState();
}
I would like to try the control, but when I add a reference to the dll in my project the items do get added to the toolbox. The only problem is that they are greyed out, so I cannot add the controls to my project.
Is this a known issue, or is there something I am doing wrong?
If they don’t immediately appear, right-click in the Toolbox and select “Choose Items…” – then click Browse and locate the DLL. The controls should then appear in the list with checkmarks beside them. When you click OK, they will appear in the Toolbox.
They do appear in the toolbox, just like you said. The only problem is that they are greyed out and thus I am unable to drag them to my form. No clue what the deal with that is.
That sounds very unusual. I’ve only ever seen that happen when trying to add controls while the code is running…
Check that both assemblies target the same version of the .NET Framework (recompile the controls DLL as necessary). If that doesn’t work, try adding the code directly into your project instead of via an assembly reference? Might help to shed some light on the cause of the problem.
i bleave the reasion for this is because the IDE was complaing about
public partial class DropDownControlBase : Control {
changeing it to
public class DropDownControlBase : Control {
works very well
is there a way to stop the parent node from being selectable? so can only select child nodes ?
To achieve this, you would have to add an additional property to ComboTreeNode. Then, in ComboTreeBox and ComboTreeDropDown, you would have to test this property during mouse/keyboard events, as well as when the SelectedNode property is changed, to make sure that the node may not be selected. You may also wish to change the appearance of nodes which cannot be selected; e.g. graying them out or not drawing the highlight when the mouse hovers over it.
Thank you, for such a quick reply on such an old project.
Is it posable to creat a method/event that is
selectedname
selectedtext
selectedindex
I looked at the source of this and now have a Disable Parent property that wont select the parent Node but the set selectedNode by name text and index is a bit beound my skils I think, I see where to do it in ComboTreeNode.cs but not sur how to write the _selectednode by name
Never mind LinkQ works just fine with some changing of the control I have the ComboTree working exactly how I need it to.
Can you please confirm that the “protected override void OnSelectedItemChanged” of “groupcombobox.cs” is not firing?
Because I have a list that I have added and it behaves very odd…
I added groups male and female
Then added lion tiger
AnamleGbid.ValueMember = “Value”;
AnamleGbid.DisplayMember = “Display”;
AnamleGbid.GroupMember = “Group”;
AnamleGbid.DataSource = new ArrayList(new object[] {
new{Display = “Tiger”, Group= “Female”, Value = 1337532130},
new{Display = “Tiger”, Group= “Male”, Value = 3},
new{Display = “Lion”,Group= “Female”, Value = -930376119},
new{Display = “Lion”,Group= “Male”, Value = 9},
});
If you click on a male lion it selects the female lion same with tiger it’s not selecting based on Value how can I change this nore is the event firing how can I change this?
Is there a way that checkboxes could be included in the treeview?
It would be possible to implement this. They would function in a similar way to the expand/collapse glyphs, in that they would capture mouse clicks without closing the dropdown or changing the selection.
Loosely speaking, you would need to:
Hi, how can I use ComboTreeBOX in Vb.net project, can you help?
If you’re not familiar with C#, I would suggest downloading the binary (DLL) package from this page. You will be able to add it as a reference in your VB.NET project by browsing to the location of the file. The control should then appear in the toolbox when you design your forms. One of the great things about the .NET Framework is that you can use any assembly in your project, regardless of whether it is written in C#, C++ or VB.NET (or any of the other .NET languages). Let me know how you get on.
Note: Visual Studio may not automatically add controls from assemblies that were downloaded from the internet. If the controls don’t appear in the toolbox immediately, you may have to add them using the ‘choose items…’ command.
Thanks for you reply. I added dll reference to my project and try to add item using ‘Choose Item’ but still the components are not listing.
It worked for me; here’s a VB.NET project containing the DLL with a ComboTreeBox added to a Form. If all else fails, you can copy and paste the control into your own project: https://www.dropbox.com/s/smpvjuo6sw1g2a5/DropDownControlsTestVB.zip?dl=0
Wow, this library is seriously cool! Just completely what I feared I had to write myself. Did not show up immediately after I referenced the library but with Tools / Choose Toolbox Items I was able to get them working.
Many thanks for such a great library!
Hey Bradley,
is it possible with this library to have a dropdown chek list, witjout the tree? I tried adding only parents to the ctbCheckboxes.Nodes, but then you get those little grey lines from the hierarchy in front of the checkboxes?
I actually made this modification in a personal project not too long ago, so I can publish an updated version containing the change. The control will simply hide the expand/collapse glyphs if there are no child nodes. Thank you for your donation too!
Hey Bradley, that is exactly what I mean, that would make the thing have even one more display style. If you could update it that would be great!
Donation well deserved, saves me a lot of time so it’s absolutely worth it
I’ve published the latest version (1.0.3) of the drop-down controls here. Enjoy!
Excellent, thanks a lot for the very quick reply and updates, keep up the good work!
Hee Bradley,
what I notice is that the CascadeCheckState does not work for more than 2 levels. I have a 6 level deep hierarchy and then it fails cascade down up all the way.
Bastiaan
Hi sir! good day, i had some question to ask , i try to use your code on my program, but seems like .GroupMember had an error saying missing a using directive or assembly reference. sorry i’m new at this things.
thank you!
Make sure that your project is targeting the correct version of the .NET Framework (either 3.5 or 4/4.5 depending on which version you downloaded). If you’re still having problems, paste the exact error message into a comment and let me know.
Here is the error
Error 1 ‘System.Windows.Forms.ComboBox’ does not contain a definition for ‘GroupMember’ and no extension method ‘GroupMember’ accepting a first argument of type ‘System.Windows.Forms.ComboBox’ could be found (are you missing a using directive or an assembly reference?
It looks like you’ve added a regular ComboBox control instead of a GroupedComboBox.
OH I see… big tnxs sir, now it’s working.
Any example for multiple group nested, atleast 3 group
ComboTreeBox will let you have multiple nested groups. For example:
ComboTreeNode n1, n2, n3;
n1 = comboTreeBox1.Nodes.Add("Orange");
n2 = n1.Nodes.Add("Cat");
n3 = n2.Nodes.Add("Techno");
n3.Nodes.Add("Square");
n3.Nodes.Add("Circle");
n3.Nodes.Add("Octogon");
n3 = n2.Nodes.Add("Rock");
n3.Nodes.Add("Pentagon");
n3.Nodes.Add("Triangle");
n2 = n1.Nodes.Add("Dog");
n3 = n2.Nodes.Add("Pop");
n3.Nodes.Add("Rhombus");
n3 = n2.Nodes.Add("Country");
n3.Nodes.Add("Hexagon");
n3.Nodes.Add("Dodecahedron");
n3.Nodes.Add("Decagon");
n1 = comboTreeBox1.Nodes.Add("Blue");
// etc