DropDownControls demo

About

This is a set of drop-down controls for Windows Forms that add a hierarchical dimension to their list items. They utilise visual styles and the Buffered Paint API to provide consistency with standard controls.

GroupedComboBox

Key features:

  • Grouping
  • Data-binding
  • Sorting
  • Visual style rendering

Extends the standard ComboBox control by adding a GroupMember property (in addition to the familiar DisplayMember and ValueMember properties). This allows you to display the drop-down list items in groups. The grouping functionality uses the PropertyDescriptor mechanism, thus it is compatible with data-binding. Although owner-drawn, the control overcomes the inconsistent visual style problem inherent to the combo box control by using visual style rendering and the Buffered Paint API.

You can use the GroupedComboBox control as a drop-in replacement whenever you need to display list items in groups.

ComboTreeBox

Key features:

  • Tree structure for list items
  • Offers similar features to the TreeView control
    • Nodes indexed by key
    • Node images
    • Font styles
    • Path separator, get/set node by its path
  • Passive drop-down (does not steal focus)
  • Support for multiple selected nodes (using checkboxes)
  • Visual style rendering

This drop-down control is built from the ground up to provide a tree-based data structure instead of a flat list. The nodes are similar to the built-in TreeNode class, offering font styles, images and the ability to index according to the Name property. By using ToolStripDropDown, its popup does not steal focus and provides a seamless user experience. When dropped down, the user can hover and scroll in the usual manner, but clicking the plus/minus glyphs will expand and collapse child nodes. The standard TreeView keyboard shortcuts are also implemented. You can optionally display the full path to the selected node in the main part of the control; the path separator is configurable. A recursive enumerator is also included to assist in walking the nodes.

The control also supports multiple selected items via the use of the ShowCheckBoxes and CheckedNodes properties. In this mode of operation, normal selection rules are suspended and checkbox glyphs are displayed beside each item. You can decide whether parent nodes behave independently of their children or not. As you check individual nodes, the main part of the control displays their concatenated text.

Use the ComboTreeBox control in situations where your list items have an n-depth tree structure, a grouped structure with large numbers of items or even when you have a flat list for which you need multi-select functionality.

Custom DataGridView column types

Also included with the latest version of the project are custom column types (based on the above controls) that can be used in the DataGridView control.

DropDownSearchBox

Key features:

  • Search/filter items in the drop-down
  • Search external data sources
  • Text input with system caret and clipboard commands
  • Asynchronous, cancelable
  • Set a minimum search term length
  • Visual style rendering

Extends the ComboTreeBox control by adding inline search functionality. The user can type a search term into the editable part of the control to kick off an asynchronous search, with the results appearing in the drop-down. The control can search within the list of drop-down items or any external data source (by handling the PerformSearch event). Selecting a result not previously visible will permanently add it to the drop-down.

Use this control to reduce clutter in otherwise lengthy drop-downs, and to make it easier for the user to find the item they want to select.

Requirements

  • .NET Framework 4.5+

Download

If you find my code useful, please consider making a donation.

Current Version: 1.1.3

Binaries and source code – GitHub

Earlier Version

For developers still using .NET Framework 3.5 or 4.0 (no async support)

Binaries (.NET Framework 4.0) – dropdowncontrols-1-0-7-bin.zip

Binaries (.NET Framework 3.5) – dropdowncontrols-1-0-7-bin-net35.zip

Visual Studio 2012 solution (includes demo app) – dropdowncontrols-1-0-7-src.zip

Notes

Glyph rendering on Windows 10

In order to accurately detect Windows 10, your application must include a manifest file with the appropriate supportedOS element, e.g:

<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
   <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
      <application>
         <!-- Windows 10 -->
         <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
      </application>
   </compatibility>
</assembly>

Related articles

A ComboBox with Grouping
A ComboBox with a TreeView Drop-Down
Painting Controls With Fade Animations Using the Buffered Paint API
Drop-Down Controls Revisited
DataGridView Column Types for Drop-Down Controls

110 thoughts on “Drop-Down Controls

  1. +5
    vote

    Hello,
    I have an issue with ComboTreBox (checkboxes).
    i.e.
    Initial condition: all nodes are unchecked.
    So, If you create nodes with deep >= 2, where 0 is initial deep, and you check=true one node in deep 0, then only children nodes with deep 1 are checked. However children nodes with deep >= 2 are not checked.
    Could you please look into it??

    Reply
    • +1
      vote

      Thanks for bringing this problem to my attention. The checkbox state was not recursing properly. I’ve released a new version of the project which fixes the issue.

      Reply
      • +2
        vote

        Hello,
        The problem is still here in version 1.0.6, althought it seems that the afterCheck event is not fired when the node’s depth >= 2.
        Thank you.

        Reply
        • vote

          Hello All,

          i think i managed to know where the problem is.

          If you are adding the ComboTreeNodes in the correct order from Up to Down (Parent first and then the Sub-Nodes), then this should be working OK.

          If you are adding the ComboTreeNode in a random way (for example you add the sub-sub-nodes to the sub-node without adding them to the parent first) then this won’t work.

          The correct order is to add the nodes from the Parent to the children not the other way.

          When i tried to add the nodes manually (using the Designer) it didn’t work. When i updated the Code to call the Add function in the order mentioned above, it worked.

          When i added the nodes by code using the correct order it worked as well.

          I hope this helps.

          P.S: Great work by the way, Bradley! 🙂


          Regards,
          Ahmad

          Reply
  2. vote

    Hi Bradley,
    I have one question..

    My code is like this and no problem with databinding bur how can i get selected item data value or group name ?

    ArrayList datas = 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},
    });

    cmbb.ValueMember = “Value”;
    cmbb.DisplayMember = “Display”;
    cmbb.GroupMember = “Group”;
    cmbb.DataSource = datas;

    Thanks for all;

    Reply
    • vote

      Retrieving the selected value with GroupedComboBox is the same as with the normal ComboBox control; simply use the SelectedValue property (i.e. cmbb.SelectedValue) and cast to the required type.

      To get the group to which the selected item belongs, use the SelectedItem property and then read the value of the Group property. Because you are using an anonymous type, you cannot access the property directly, however under .NET 4 and newer, you can use the dynamic keyword:

      dynamic item = cmbb.SelectedItem;
      Console.WriteLine("The selected group is {0}.", item.Group);

      On .NET 3.5 and older, you can use reflection to achieve the same thing:

      object item = cmbb.SelectedItem;
      Console.WriteLine("The selected group is {0}.", item.GetType().GetProperty("Group").GetValue(item, null));

      Reply
      • vote

        Hi Brad, Sorry to bug you on old post.But I have one quick doubt on the above same example.

        Say, I am choosing the Lion display member in Male group, then with the “selecteditem”, I get the correct value.

        But on revisiting the drop down, the highlighted item is the Lion display member on Female group instead of Male group.

        I am guessing that on duplicate values across group, the first group value equal to selected value is highlighted instead actual of selected index. I used your DLL and didn’t check your source code. Tell me if I am not clear.

        Reply
        • +1
          vote

          (For the benefit of anyone else reading this thread, he’s talking about the GroupedComboBox control)

          I was able to reproduce the problem you described, but only when DropDownStyle was set to DropDown (not DropDownList). The selection behaviour is inherited from the built-in ComboBox control, which behaves in exactly the same way. I think this is because editable combo boxes effectively ignore the ValueMember property and match solely on the item text.

          The only way you can solve this is to change the DropDownStyle back to DropDownList, or change the data so that there are no two items with the same value for DisplayMember.

          Reply
          • vote

            Changed as DropDownList and its working as intended. Thanks for the explanation!!!

  3. vote

    Hi,

    there is an issue with combobox columns in DataGridView. The problem is that you have to click twice on the cell to open the drop down part. On standard combobox you need to click only once. I suppose this is caused by the controls structure and event firing when clicked on a cell. I’ve tried to figure out how to fix it but I didn’t really find the fix. If you have any idea how to do it, please let me know. Thanks.

    Reply
    • vote

      Hi once again,

      I’ve found a workaround… when placing in DropDownCellBase in
      protected override void OnMouseEnter(int rowIndex)

      DataGridView.CurrentCell = DataGridView.Rows[rowIndex].Cells[OwningColumn.Index];
      you need to click only once on the combobox. Hope this helps you 🙂

      Reply
      • vote

        Using the OnMouseEnter event is not the greatest because if you move your mouse over the cell you lose any selection you previously had.

        Instead, in the DropDownCellBase, change your OnMouseDown override to this:

        protected override void OnMouseDown(DataGridViewCellMouseEventArgs e) {
        base.DataGridView.CurrentCell = base.DataGridView.Rows[e.RowIndex].Cells[base.OwningColumn.Index];

        _wasCurrentCell = (DataGridView.CurrentCellAddress == new Point(e.ColumnIndex, e.RowIndex));
        base.OnMouseDown(e);
        DataGridView.InvalidateCell(e.ColumnIndex, e.RowIndex);
        }

        Reply
    • +1
      vote

      I’m sure it could be adapted, but as i’m not familiar with the rules for layouts in other languages, I am not the best person to implement it.

      Reply
  4. vote

    Hi Bradley,
    Great code, really useful. One problem i’m having though. Say you have this order (using your example)
    var groupedItems = new[] {
    new { Group = “Gases”, Value = 1, Display = “Helium” },
    new { Group = “Gases”, Value = 2, Display = “Hydrogen” },
    new { Group = “Gases”, Value = 3, Display = “Oxygen” },
    new { Group = “Gases”, Value = 4, Display = “Argon” },
    new { Group = “Radioactive”, Value = 5, Display = “Uranium” },
    new { Group = “Radioactive”, Value = 6, Display = “Plutonium” },
    new { Group = “Radioactive”, Value = 7, Display = “Americium” },
    new { Group = “Radioactive”, Value = 8, Display = “Radon” },
    new { Group = “Metals”, Value = 9, Display = “Iron” },
    new { Group = “Metals”, Value = 10, Display = “Lithium” },
    new { Group = “Metals”, Value = 11, Display = “Copper” },
    new { Group = “Metals”, Value = 12, Display = “Gold” },
    new { Group = “Metals”, Value = 13, Display = “Silver” }

    };
    And you want the groups to display in that order (Gases->Radioactive->Metals) is this possible or do the groups have to be ordered alphabetical?

    Best Regards,
    Ashley

    Reply
    • vote

      The GroupedComboBox control always sorts both the groups and items alphabetically using the default comparer. The internal items collection is sorted in order to guarantee that each item will appear under the appropriate group heading. Because it uses an unstable sort to do this, it is not possible to preserve the original order of the groups or items. If you comment-out the line in the SyncInternalItems() method containing the call to _internalItems.Sort(this) then you can disable the internal sorting; however, you will have to guarantee that the items in the DataSource are in the correct order (as in your code example) – otherwise you will get unpredictable behaviour.

      I may add support for custom sorting in a future version of the control, but it will have to operate differently to the current implementation.

      Reply
  5. vote

    Hi Bradley,

    Great code. Exactly what, I am trying to implement!!
    I need to a treeview in datagridview column. I tried using your ComboTreeBoxColumn type in datagridview.
    My question is, Can I show checkboxes for this treeview in datagridview? If yes, which property should be used for this?
    I checked showcheckboxes and checknodes, but those are applicable to comboboxtree. Sorry if I am sounding ignorant.

    Reply
    • vote

      Unfortunately, the checkbox options are not yet supported by the ComboTreeBoxColumn type. This is because they would change the meaning/type of the cell’s Value property and I need to devise a sensible way of dealing with that. This is complicated further by the requirement for DataGridView cell values to be convertible to/from strings; if each cell may contain multiple checked values, it is difficult to parse and format these in a consistent way. I will look into this further at a later date and, if possible, update the controls to support these options.

      Reply
  6. vote

    Hello,

    I’m not getting any images in the ComboTreeBox. My code is pretty straightforward:


    Me.cbtbDatabaseItems.Images = Me.ImageList1

    Dim ndX As New ComboTreeNode
    ndX.Name = "Artiestnaam"
    ndX.ImageIndex = 0
    ndX.ExpandedImageIndex = 0
    ndX.Text = "Artiestnaam"

    Me.cbtbDatabaseItems.Nodes.Add(ndX)

    ndX = New ComboTreeNode
    ndX.Name = "Titel"
    ndX.ImageIndex = 1
    ndX.ExpandedImageIndex = 1
    ndX.Text = "Titel"

    Me.cbtbDatabaseItems.Nodes.Add(ndX)

    What am I doing wrong?

    Reply
    • vote

      Looks like you’ve found a bug. You can fix this if you’re compiling from the source, by changing the code in ComboTreeDropDown.cs, line 202 so that it reads:

      // composite the image associated with node (appears at far right)
      g.DrawImage(nodeImage, new Rectangle(
      bmpWidth - nodeImage.Width,
      composite.Height / 2 - nodeImage.Height / 2,
      nodeImage.Width,
      nodeImage.Height
      ));

      Reply
      • vote

        Hi Bradley,

        I mean, I’m not getting any images in the dropdownlist. Once I’ve selected an item, the image is shown in the combobox.

        Regards,
        Coen van Elst

        Reply
  7. vote

    Hi Bradley

    This is a great piece of code, and I am using it on my application. However, I am using this on almost ever screen I build, and some of my treeviews in this combobox are quiet big and take a while to build. How can I template the data in this. I tried declaring it as a public variable and populate it, but when I assign the object to the variable, the object is blank. I also tried populating one object with the data, then telling new combotreebox equal to the primary object, but that did not work either. Any suggestions?

    Thanks in advance
    Bradley Wheeler

    Reply
    • vote

      I’m not sure what you mean by ‘template the data’ – do you mean share a common set of nodes across several controls? If so, the problem here is that each node may only belong to a single collection (and therefore control). This is the way I designed the control, so currently there is no way to do this without modifying the source code.

      The change you would need to make would be to the Nodes property:

      public ComboTreeNodeCollection Nodes {
      get { return _nodes; }
      set {
      if (value == null) throw new ArgumentNullException("value");

      if (_nodes != null) {
      _nodes.AfterCheck -= nodes_AfterCheck;
      _nodes.CollectionChanged -= nodes_CollectionChanged;
      }

      _nodes = value;
      _nodes.CollectionChanged += nodes_CollectionChanged;
      _nodes.AfterCheck += nodes_AfterCheck;
      }
      }

      This will allow you to do something like the following:

      comboTreeBox2.Nodes = comboTreeBox1.Nodes;

      Reply
    • vote

      No, however I should note that ‘select’ fields on Web forms already support grouping. To get tree functionality, however, you would have to develop a completely custom solution.

      Reply
  8. vote

    Hello!
    normally we get comboBox selected item’s value like this:
    myComboBX.selectedValue.
    How to get checked items values in ComboTreeBox (using checkboxes)?

    Reply
    • 0
      vote

      Use the CheckedNodes property to get the checked items. You can inspect the properties of each item (Text, Tag, etc) or use GetFullPath() to get the path of each checked item.

      Reply
  9. vote

    Hi Bradley.

    First of all a great job , congratulations.

    I want to ask if esposible activate the visual effects of GroupedComboBoxCell in DataGridView ?

    Reply
  10. vote

    A really nice control — thank you for sharing! I’m using the ComboTreeBox in a ToolStrip by hosting it in a ToolStripControlHost. This works, but visually it doesn’t look like other toolstrip controls.

    I was wondering, since you started with a ToolStripComboBox, if it’s possible to put all of the code (the “controller” logic) for the ComboTreeBox in the in the ToolStripComboBox too? The entire control would derive from ToolStripComboBox, not just the drop-down. Do you think this is possible? Anything I should look out for before going down this path?

    Reply
    • +1
      vote

      Since the control currently extends DropDownBase (which itself just extends Control), you would have to make it extend ToolStripItem instead. This means that you would have to do all the rendering of the control manually as well. The ComboTreeNode and ComboTreeDropDown classes would remain virtually the same, but you would have to significantly rework ComboTreeBox itself.

      Reply
  11. vote

    Hi Bradley,

    there is a small problem with the controls. It’s about events executed after the control was showed. Do folowing tests:
    1. Open GroupedCombobox(list), without selecting anyting, When the combobox is shown, try to open ComboTreeBox(normal) -> it’s impossible to open the ComboTreeBox, you have to click once again – that’s the correct behaviour
    2. Now do the same in other direction, first open ComboTreeBox, and then click on GroupedComboBox – its opened direct – this can cause problems when the dropdown controls are used within DataGridView and nested forms.

    Reply
  12. vote

    Hello,
    Thanks for this great control. I have an issue with mono
    Unhandled Exception:
    System.NullReferenceException: Object reference not set to an instance of an object
    at GroupedComboBox.ToggleStyle () [0x00000] in :0
    at GroupedComboBox.OnDropDownStyleChanged (System.EventArgs e) [0x00000] in :0
    at System.Windows.Forms.ComboBox.set_DropDownStyle (ComboBoxStyle value) [0x00000] in :0
    at System.Windows.Forms.ComboBox..ctor () [0x00000] in :0
    at GroupedComboBox..ctor () [0x00000] in :0
    at (wrapper remoting-invoke-with-check) GroupedComboBox:.ctor ()
    at Test.GroupedToolStripComboBox+ToolStripGroupedComboBox.CreateControlInstance () [0x00000] in :0
    at Test.GroupedToolStripComboBox+ToolStripGroupedComboBox..ctor () [0x00000] in :0
    at (wrapper remoting-invoke-with-check) Test.GroupedToolStripComboBox/ToolStripGroupedComboBox:.ctor ()
    at Test.UI.Main.InitializeComponent () [0x00000] in :0
    at Test.UI.Main.ctor () [0x00000] in :0
    at (wrapper remoting-invoke-with-check) Test.UI.Main:.ctor ()
    at Test.UI.Main.Main () [0x00000] in :0

    I hope you can fix this.

    Reply
    • vote

      It looks like the Mono version of Windows Forms is implemented differently than the official .NET Framework assembly; it is firing the DropDownStyleChanged event in the constructor for the ComboBox class. This should not occur, and does not fire in the Microsoft implementation. My controls are designed for the .NET Framework only, they are untested and unsupported on Mono. To solve this on Mono, you will need to change the OnDropDownStyleChanged method so that nothing happens until after the base class constructor has been called.

      Reply
  13. vote

    Hey Bradley! thanks for this wonderful control.
    However I encouter an issue (I’m on VS2015). I added the dropDownControls project to my solution (It was easier), but an exception shows up saying that ‘DataGridViewPaintParts’ and “MouseButtons” don’t have a definiton for “HasFlag”.
    This exception doesn’t show in the demoApp.
    Do you have an idea where it could come from?
    Thanks a lot.

    Reply
    • vote

      The Enum.HasFlag method was introduced in .NET 4.0, so if your project is targeting an earlier version of the framework then you will need to replace those calls with the equivalent code:
      e.g. value.HasFlag(MouseButtons.Left) can be rewritten as ((value & MouseButtons.Left) == MouseButtons.Left)
      If you are using .NET 3.0 then you can write an extension method to replace the missing method.

      Reply
    • vote

      I have released an updated version (1.0.7) which includes a DropDownWidth property. The dropdown portion must be at least as wide as the control.

      As for horizontal scrollbars, I deliberately chose not to implement these because they are not consistent with good UI design. If the items do not fit horizontally within the dropdown portion, a different type of control (perhaps even a separate dialog box) should be used to display the choices.

      Reply
  14. vote

    Hello Bradley Smith, I hope you are doing well.

    I congratulate you for such great control, I have a detail when dynamically filling the ComboTreeBox, since in each load I should clean the .Text, but the text is loaded with the previous selection … what solution you have to help me. Thank you

    Reply
  15. vote

    Hi Bradley,
    first of all thanks for sharing this great custom control.
    I want to share with you this strange behavior I experienced: I tried to fix the windows 10 blurry problem of windows form (during debug) using the following fix:

    http://crsouza.com/2015/04/13/how-to-fix-blurry-windows-forms-windows-in-high-dpi-settings/#comment-1319

    However after this fix the ComboTreeBox starts rendering in a strange way. Here the link of how the control looks like before and after the blurry fix:
    – Before: https://ibb.co/gEK80k
    – After: https://ibb.co/fyTCRQ

    Do you have any suggestion how to have both working well, or maybe how to better fix the blurry problem?

    Thanks in advance,
    kind regards.

    Note: the blurry problem is not only a visual problem, also sizing of the objects I set at design time changes at run time, this is the reason why I wanted to fix it.

    Reply
    • vote

      Thanks for the feedback. I did not really design these controls with high-DPI support in mind; many of the internal metrics operate on the assumption that the display will always be 96dpi.

      The method you followed is certainly the recommended approach for WinForms apps, so you’re not doing anything wrong in that respect. However, because of the reasons stated above, the ComboTreeBox will require changes in order to look right at different DPIs.

      The reason why the plus/minus glyphs appear too large is that the code in the GenerateBitmap method (in ComboTreeDropDown.cs) uses a fixed 16×16 pixel square as the bounds for the glyph. At 96dpi, the VisualStyleRenderer will draw a small glyph inside this square but, at larger DPIs, it seems that it will allow the glyph to fill the entire square. In theory, this could be fixed by changing the GLYPH_SIZE constant to a smaller number (e.g. 10). The bounds of the glyph would need to be changed slightly as well:
      Rectangle glyphBounds = new Rectangle(indentation + (INDENT_WIDTH / 2 - GLYPH_SIZE / 2), composite.Height / 2 - GLYPH_SIZE / 2, GLYPH_SIZE, GLYPH_SIZE);

      I cannot easily explain why the text is too large, as the height of each item in the dropdown is determined by the size of the font and therefore should always be able to accommodate the text. I was able to improve the fit at larger font sizes by adding an arbitrary amount onto the calculated height:
      _itemHeight = Math.Max(MIN_ITEM_HEIGHT, Font.Height + 3);

      This may go some length to addressing your problems. I wish I could help more, but I do not currently have access to a high-DPI display so I am unable to test these code changes. My preference would be to remove all of the hard-coded metrics and replace them with values that scaled properly with the DPI of the display.

      Reply
  16. vote

    Thanks for the prompt response.
    Justo to complete the picture, the problem I’m experiencing is on Windows 10, display scaling level to 125%, 140 dpi monitor (is a 15.6″ full HD on laptop).
    If I bring back the scaling level to 100% the control works well even at 140 dpi. The problem seems to be the scaling, by the way also Visual Studio native controls such as data grid view have some strange behavior while setting dimension.

    Thanks & regards.

    Reply
  17. vote

    At first thank you, yours controls are very usefull

    I have just a question. The control for Datagridview need “double-click” for appear list.
    Is there any simple solution for change it on simple-click?

    Thank you & regards

    Reply
    • vote

      This behaviour is consistent with the built-in DataGridViewComboBoxColumn, which requires one click to place the cell into ‘edit mode’ and a second click to drop down the list. You can change the behaviour for all columns in the grid by setting the EditMode property of the DataGridView to EditOnEnter.

      Reply
  18. vote

    Hi Bradley,
    Thanks a lot I really appreciate your tool, it’s just so great!
    I’m also doing some maintenance on a VB2005 application and the combotreebox functionality is just what the doctor ordered for what I need to do. I can only get the controls into the toolbox using the Choose Toolbox Items option. However when I try to add the ComboTreeBox onto a form I get an error (although I can add the GroupedComboBox control without a problem). I add references to System.Design and WindowsBase but this has not helped. I’m using the dll for framework 3.5:
    Failed to create component ‘ComboTreeBox’. The error message follows:
    SYstem.IO.FileLoadException: The given assembly or codebase was invalid. (Exception from HRESULT 0x80131047) at System.Reflection.AssemblyName.nInit(Assembly& assembly, Boolean forIntrospection, Boolean raiseResolveEvent).

    Reply
    • vote

      I haven’t seen this error before. I’m wondering if there could be some dependency on the C# system assemblies. Could you try adding the control to a C# project and see if you get the same error message?

      Reply
  19. vote

    Hi Bradley,
    Brilliant controls. One question… Somewhere between version 1.04 and 1.07 the ShowOnlyNodeName property of the ComboTreeBox was removed. Is there an equivalent in 1.07?
    Thanks,
    Michael

    Reply
    • vote

      Hi Michael,
      Yes, I simply renamed the property to ShowPath and reversed its meaning. You would set this to false to show only the text for the selected node. I think it makes more sense this way.

      Reply
    • vote

      As I mentioned in this earlier comment, I am not familiar with the rules for RTL layouts. If anyone wishes to contribute code which implements this functionality, I would be happy to add it to the project (with attribution).

      Reply
  20. vote

    I am failing to retrieve the checked items from the ComboTreeBox, please help me.
    In fact i am pointing to the Value of the checked items from the ComboTreeBox.

    Reply
  21. vote

    I will join the choir of people praising the awesomeness of this control. It’s great!

    A minor thing: GetNodeAt does not seem to exist for ComboTreeBoxColumn. I solved it by simply copying the method from ComboTreeBox.cs to ComboTreeBoxColumn.cs and adjusting a couple of variable names, like so:

    public ComboTreeNode GetNodeAt(string path)
    {
    return this.Nodes.ParsePath(path, this.PathSeparator, this.UseNodeNamesForPath);
    }

    Reply
  22. vote

    Very nice library. For a small project I’m working on, I need a tool that supports 2 layers of groups, but only allow the items in the lowest group to be selected.

    Using ComboTreeNode, there is an option “Selectable” (in version 1.0.8), however, it does not seem to do anything. Using e.g. the DropDownSearchBox and having set all items to “Selectable = false”, still allows me to select everything.

    Another thing I noticed, when you search, it does show the correct results, but the groups are missing. In a way that makes sense, but there are situations in which you would like to show the group in which the item was found as well as the item.

    Reply
    • vote

      You’re right – Selectable appears to do nothing. I think something went wrong the last time I merged my changes.

      I’ve taken the opportunity to release a version 1.0.9 which fixes this problem and also includes an example of how you can handle the PerformSearch event on DropDownSearchBox to retain groups in the search results.

      Reply
  23. vote

    That was quick! Guess I have to implement the ComboTreeNode again than! While I was implementing the GroupedComboBox, I noticed that the dropdown field is the same width as the combobox. My long text were not readable, hence I made a little adjustment.

    https://pastebin.com/e5Kjs4vr

    I didn’t find it on github, else I would send in a pull request. The code is not yet perfect (see comment on top) but for me it worked as required today. Lastly, do you have the binaries available on nuget? Ifso, it might be good to add a link on the site 🙂

    Reply
  24. vote

    the library does not work in VS2008. I see that it is in 3.5 but I can not put it in the form, this comes out:

    —————————
    Microsoft Visual Studio
    —————————
    Error al crear el componente ‘ComboTreeBox’. El mensaje de error es el siguiente:
    ‘System.IO.FileLoadException: El nombre de ensamblado o el código base dado no es válido. (Excepción de HRESULT: 0x80131047)

    en System.Reflection.AssemblyName.nInit(Assembly& assembly, Boolean forIntrospection, Boolean raiseResolveEvent)

    en System.Reflection.AssemblyName.nInit()

    en System.Reflection.AssemblyName..ctor(String assemblyName)

    en Microsoft.VisualStudio.Design.VSTypeResolutionService.GetType(String typeName, Boolean throwOnError, Boolean ignoreCase, ReferenceType refType)

    en Microsoft.VisualStudio.Design.Serialization.CodeDom.AggregateTypeResolutionService.GetType(String name, Boolean throwOnError, Boolean ignoreCase)

    en Microsoft.VisualStudio.Design.Serialization.CodeDom.AggregateTypeResolutionService.GetType(String name)

    en System.ComponentModel.TypeDescriptor.CreateDesigner(IComponent component, Type designerBaseType)

    en System.ComponentModel.Design.DesignSurface.CreateDesigner(IComponent component, Boolean rootDesigner)

    en Microsoft.VisualStudio.Design.VSDe…’

    Help me please.

    Reply
    • vote

      I have not been able to reproduce this issue. I am no longer updating the .NET 3.5 version of the controls. I strongly advise checking out the current version, which works with .NET 4.5 and higher.

      Reply
  25. vote

    Hello. Great job. I get an error:
    Can not convert a ‘ComboTreeNode’ object to an object ‘System.Collections.Generic.IEnumerable`1 [ComboTreeNode]’. ‘

    Public Function FromTableCb(ByVal dt As DataTable, ByVal parent As String, ByVal node As String, ByVal name As String) As ComboTreeNode()
    Dim tnodes As New List(Of ComboTreeNode)
    Dim columns As String() = New String(2) {parent, node, name}

    If dt.Columns.Contains(parent) AndAlso dt.Columns.Contains(node) AndAlso dt.Columns.Contains(name) Then
    dt.DefaultView.RowFilter = “[” & parent & “] = 0”
    For Each r As DataRowView In dt.DefaultView
    tnodes.AddRange(ReadNodesCb(columns, r, dt))
    Next
    Return tnodes.ToArray()
    Else
    Return tnodes.ToArray()
    End If
    End Function

    Private Function ReadNodesCb(ByVal columns As String(), ByVal r As DataRowView, ByVal dt As DataTable) As ComboTreeNode
    Dim cn As New ComboTreeNode()

    cn.Name = r(columns(2)).ToString()
    cn.Text = cn.Name

    Me.GetAllNodesCb(columns, cn, dt, CInt(r(columns(1))))
    Return cn
    End Function

    Private Sub GetAllNodes(ByRef dt As DataTable, ByVal pn As ComboTreeNode, ByVal parentid As Integer, ByRef id As Integer)
    For Each cn As ComboTreeNode In pn.Nodes
    id += 1
    dt.Rows.Add(parentid, id, cn.Name)
    Me.GetAllNodes(dt, cn, id, id)
    Next
    End Sub

    Private Sub GetAllNodesCb(ByVal columns As String(), ByRef pn As ComboTreeNode, ByVal dt As DataTable, ByVal nodeid As Integer)
    dt.DefaultView.RowFilter = (“[” & columns(0).ToString() & “] = “) + nodeid.ToString()

    For Each r As DataRowView In dt.DefaultView
    Dim cn As New ComboTreeNode()

    cn.Name = r(columns(2)).ToString()
    cn.Text = cn.Name

    pn.Nodes.Add(r(“nodetitle”).ToString)
    Me.GetAllNodesCb(columns, cn, dt, CInt(r(columns(1))))
    Next
    End Sub

    With the same code I fill a treeview from database, but I got the error when I fill a ComboTreeBoxColumn.

    Any idea?

    Reply
  26. vote

    The DropDownSearchBox doesn’t seem to allow collapsing/expanding the ancestor nodes. Is this intended functionality? I don’t see an obvious choice to AllowCollapsing or anything, probably a rookie mistake. Thanks!

    Reply
    • vote

      You’re right – this seems to be a bug! In actual fact, the plug/minus glyphs are supposed to be hidden by default for the DropDownSearchBox. You can re-enable them by setting the ShowGlyphs property to true. I will publish an updated version soon.

      Reply
      • vote

        I Bradley, I work with Lucas and I was able to find that when I set the ShowGlyphs property to true, at some point the constructor for DropDownSearchBox resets this property to false. I comments out this line to get it to work. Is there a better fix for this?

        Reply
        • vote

          I don’t fully understand how Visual Studios handles the designer code but I think the inconsistency between _showGlyphs defaulting to “true” in ComboTreeBox and it being set to “false” in the DropDownSearchBox constructor is confusing the Visual Studios designer. The designer only puts the set property code this.dsbListItems.ShowGlyphes =
          true;
          in the Designer code if the user sets the value to something different than the stated default. So when the demo code for DropDownSearchBox is run the constructor sets ShowGlyphs to false but the designer never inserted the code to set it to “true” even thought I set the property in the designer. I hope this helps you to fix this in your next release.

          Lines to consider:
          DropDownSearchBox.cs:Line 85 (in the constructor)
          ComboTreeBox.cs:Line 139 ([DefaultValue(true),…)

          Reply
  27. vote

    Thank you so much for these great controls. This is concerning the DropDownSearchBox. When your demo app is placed near the bottom of the screen so that the selection boxes could run off the screen, the selection box moves up so that all the data shows. Sometimes, this covers up the actual box area that you type into. Is there a way to get it to show the selection list above the box, which is similar to how your demo Grouped Combo Box works?

    Reply
    • vote

      Ah yes, I see what you mean. The ToolStripDropDown component will automatically reposition itself if it doesn’t fit within the working area of the screen, but the built-in logic isn’t aware of the underlying control. I’ve made a few changes to the ComboTreeDropDown class to deal with this scenario: 1) Detecting whether the dropdown will overflow the screen, and repositioning itself above the control, and 2) Repositioning the dropdown if its height changes while open. You can see these changes on the GitHub page. They will eventually be included in an official release.

      Reply
  28. vote

    Hi,
    Compliment for the great control you made!!

    I’m using the binaries version 1.0.7 in Visual Basic, in particular the ComboTreeBox control. (I’m actually bind to develop with Visual Studio 10 and .NET 4.0).

    There is a way to define a node as “disabled”?
    My intent is to show the node in the combobox, but not let the user to select it. Mainly I need it on the nodes that are not a leaf.
    Actually I’m marking them with a particular tag, and once the user select them, reset the SelectedNode as nothing (not very nice effect, but the best that I could think).

    PS I noticed some strange behavior, if by mistake I define the property Expanded as True on a node without children, the Image displayed on the node is the first defined in the associated ImageList, and not the one defined in ImageKey/ImageIndex property

    Reply
    • vote

      Thanks for your interest in my controls. I added a Selectable property to the ComboTreeNode class in a later release – setting this to false on the parent nodes should achieve what you want.

      The other issue you reported is still present in the current version, so I will fix this shortly.

      I recommend that you grab the latest version from GitHub and compile from source – it should be possible to target the .NET Framework 4.0 with minimal modifications if this is a requirement for you.

      Reply
  29. vote

    Hi,

    thanks for the suggestion and for solving the issue (very quick response).

    I’ve done this, while crossing the finger due to my limited knowlegde of C# 😀

    – Installed Visual Studio 2019 (community version)
    – Changed the target to .NET 4.0
    – Rebuilt the “DropDownControls” project

    I received the following warning, but it worked smoothly with no need of changes on your code:

    ------ Rebuild All started: Project: DropDownControls, Configuration: Debug Any CPU ------
    C:\Workspace\DropDownControls-1.1.4\BufferedPaint\BufferedPainter.cs(423,131,423,137): warning CS1573: Parameter 'anchor' has no matching param tag in the XML comment for 'VisualStateTrigger.VisualStateTrigger(VisualStateTriggerTypes, TState, Rectangle, AnchorStyles)' (but other parameters do)
    C:\Workspace\DropDownControls-1.1.4\DataGridView\DropDownColumnBase.cs(124,27,124,39): warning CS1591: Missing XML comment for publicly visible type or member 'DropDownCellBase.OnMouseEnter(int)'
    C:\Workspace\DropDownControls-1.1.4\DataGridView\DropDownColumnBase.cs(129,27,129,39): warning CS1591: Missing XML comment for publicly visible type or member 'DropDownCellBase.OnMouseLeave(int)'
    C:\Workspace\DropDownControls-1.1.4\DataGridView\DropDownColumnBase.cs(134,27,134,38): warning CS1591: Missing XML comment for publicly visible type or member 'DropDownCellBase.OnMouseDown(DataGridViewCellMouseEventArgs)'
    C:\Workspace\DropDownControls-1.1.4\DataGridView\DropDownColumnBase.cs(140,27,140,36): warning CS1591: Missing XML comment for publicly visible type or member 'DropDownCellBase.OnMouseUp(DataGridViewCellMouseEventArgs)'
    C:\Workspace\DropDownControls-1.1.4\DataGridView\DropDownColumnBase.cs(145,27,145,39): warning CS1591: Missing XML comment for publicly visible type or member 'DropDownCellBase.OnMouseClick(DataGridViewCellMouseEventArgs)'
    C:\Workspace\DropDownControls-1.1.4\DropDownControlBase\DropDownControlBase.cs(255,28,255,40): warning CS1574: XML comment has cref attribute 'StyleChanged' that could not be resolved
    DropDownControls -> C:\Workspace\DropDownControls-1.1.4\bin\Debug\DropDownControls.dll
    ========== Rebuild All: 1 succeeded, 0 failed, 0 skipped ==========

    The control work exactly as I intended.
    Thank you very much and again compliment for your work

    Reply
  30. vote

    Hi, your work is very nice. Is there any possibility of being able to check in the ComboTreeBoxColumn just like in ComboTreeBox?

    Reply
    • vote

      The main reason I chose not to implement this feature is that I can’t see a good way of getting it to work with data binding. When the control only allows a single node to be selected, the Value property of the cell can simply be a string containing the path. If you allow multiple nodes to be selected, what would you expect the Value to be? And if the DataGridView was bound to a data source, how would the data indicate this?

      Reply
  31. vote

    Hi Bradley,
    is possible to integrate DropDownSearchBox functionality for searching into ComboTreeBox component without loosing hierarchy tree and expanding tree nodes ?

    Thx for ur time.

    Reply
    • +1
      vote

      Yes, this is possible. An example is provided in the DemoApp project (included in the source code). By handling the PerformSearch event, you can control which nodes appear in the results.

      This is the event handler from the demo project:

      void dsbListItems_PerformSearch(object sender, PerformSearchEventArgs e) {
      	foreach (ComboTreeNode node in dsbListItems.AllNormalNodes) {
      		e.CancellationToken.ThrowIfCancellationRequested();
      
      		if (dsbListItems.DefaultSearchPredicate(node, e.SearchTerm)) {
      			// get all ancestor nodes (including the result)
      			Stack<ComboTreeNode> ancestors = new Stack<ComboTreeNode>();
      			ComboTreeNode current = node;
      			while (current != null) {
      				ancestors.Push(current);
      				current = current.Parent;
      			}
      
      			// copy ancestor nodes into search results (or re-use existing)
      			ComboTreeNodeCollection collection = e.Results;
      			while (ancestors.Any()) {
      				current = ancestors.Pop();
      
      				ComboTreeNode copy = e.Results.Find(x => dsbListItems.DefaultEquivalencePredicate(x, current), true);
      				if (copy == null) collection.Add(copy = current.Clone());
      
      				collection = copy.Nodes;
      			}
      		}
      	}
      
      	e.Handled = true;
      }
      Reply
  32. vote

    Hi Bradley,
    First of all thanks to the great work in the ComboTreeBoxColumn in the Drop Down Controls
    there is some issue with the combo when I used RTL property in the dataGridView , the dropped list draw from the start point of the combo cell and goes all the way left .. and covered the other columns , it should go right when RTL is used

    for now i will try to find a solution .. i hope you will fix it
    best wishes
    .
    .
    no one from the beloved Sudan

    Reply
    • vote

      Thanks for the kind words 🙂 The controls were never designed with RTL in mind, so I would have to do some research on how this is meant to be implemented. Keep an eye on the Github page for any updated releases.

      Reply
      • vote

        Hi Bradley,
        after 2 days of searching in the source code finaly i found a solution and here its :

        in ComboTreeDropDown class > open() method
        adding this simble if before the Show method
        if (_sourceControl.RightToLeft == RightToLeft.Yes)
        {
        Show(_sourceControl, new Point(_sourceControl.ClientRectangle.Width, _sourceControl.ClientRectangle.Height));

        }
        else
        {
        Show(_sourceControl, new Point(0, _sourceControl.ClientRectangle.Height));
        }

        .
        .
        .
        thats fix the problem

        Reply
  33. vote

    Hi Bradley,
    Thanks for the controls, the ComboTreeBox has been a lifesaver, I can’t believe after all this time something like your implementation hasn’t been included as a standard control in .NET.
    I’m hoping to get your help, I have found a ‘quirk’ that effects the ComboTreeBox and the DropDownSearchBox, if you have an ampersand in the treeview node name for example, ‘This & That’, it’s displayed as a menu shortcut the ampersand is removed and the next character is underlined like so ‘This _That’. Checking the value of the name still returns ‘This & That’ so it’s only an issue with displaying the name in the control.
    Is there any way to stop this from happening or if it’s intentional would it be possible to only do this if the next character isn’t a space?

    Thanks

    Reply
    • vote

      Hi, thanks for the kind words and feedback. From your description it would seem that the text on these items is being rendered without the NoPrefix flag. You will find this is quite common in Windows Forms generally, including the built-in TreeView control. The easiest way to work around this is to escape the ampersand with another ampersand, e.g. ‘This && That’

      In a future update I will likely add a UseMnemonic property to the control (defaults to true) to mirror the behaviour of the Label control.

      Reply
  34. vote

    Hi that is a very nice control.
    It is possible to insert a empty group in ComboBoxTree? For Example

    all
    group1
    – group 1 / item 1
    – group 1 / item 2
    group2
    – group 2 / item 1
    – group 2 / item 2

    My empty group is here the first item “all”.

    when I insert my empty group with this code

    ArrayList datas = new ArrayList(new object[] {
    new{Display = “”, Group= “all”, Value = 0},
    new{Display = “Item 1”, Group= “Group 1”, Value = 1},

    The first diplayed group has the name “all” but “all” have a empty item. That don’t look nice.

    I need a group combobox or tree where I can select a group or group item and the first item have the name “all”.

    Thanks

    Reply
    • vote

      Yes, I intend to do one final release with multi-targeting before I archive the project. Keep an eye on the GitHub repo.

      Reply
  35. vote

    Hi,
    Is it possible in ComboTreeBox to expand non-selectable node by clicking on its text without reopening ComboTreeBox?
    Thanks, very usefull library.

    Reply
  36. vote

    Hi Bradley,

    Awesome ontrol, thanks for taking the time to develop it. I’m trying to implement into an app where the nodes on the grid are loaded dynamically – so i start off with a base set of node but would like to click on a node and then an event would load the data under the expanded nod, if it exists – I have similar functionality in a normal TreeView, is this possible in your control?

    kind regards

    Craig

    Reply
  37. vote

    Hello Bradley, This is such an awesome control! Wanted to ask when using your ‘DropDownControls Demo’ under ‘DropDownSearchBox (list items)’ with or without ‘Show groups in search results’ doing a search like ‘ium’ I get 5 choices, check any off gets no results. Is there a fix for that? or am I just not doing something wrong?
    Thanks in advance.
    Jim

    Reply
  38. vote

    Hi Bradley, this is great library, just have one question

    For DrowpDownSearchBox, Paste from clipboard (Ctrl + V) does not work unless you do these options

    1. Right Click and select Paste in dropdown menu
    2. Write any char and then paste using Ctrl + V,

    Is there a way that control accept clipboard paste once focus is received and without having to write any char first?

    Hope being clear in explanation

    Regard

    Reply
    • vote

      Thanks for the kind words. I don’t do a lot of development in Windows Forms anymore, but if there’s enough interest I might consider revisiting the project. I experimented with multi-column dropdowns a number of years ago and, while they have some niche uses, they don’t really follow good UI design principles. If you find yourself hiding too much information in a dropdown, a separate window or dialog box may be a more appropriate solution.

      Reply
  39. vote

    Hi Bradley.
    Thank you for the great work you’ve done with those controls.

    I’m trying to deal with ComboTreeBoxColumn and having such a problem.
    The DatagridView itself is data binded (except that column). I buld ComboTreeBoxColumn nodes from another datasource beforehand in a way that text contains user readable name and tags are ID of the nodes from database. Then, once it’s datasource loaded with data from DataTable, I’d like to set selected value in this column based on IDs I get for each row.
    I am trying to do that by setting Value property of the corresponding cell with path to the desired node at Form Load or Form Shown, no matter, with the same result. That value remains set up until Datagridview shown for the first time, then all values are reset.
    What I am doing wrong and what is the best way to set values for this type column on form load?

    Thank you in advance.

    Reply
    • vote

      Could you perhaps share some example code that demonstrates this issue? I’ve experimented with setting a cell’s value before the DataGridView is shown, and it did not change afterwards; either with or without data-binding. It’s possible in your case that data-binding is occurring sometime after the form loads, in which case you should probably set any unbounded cell values in a handler for the DataGridView.DataBindingComplete event instead.

      Reply

Leave a reply

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> 

required