Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Windows Form - How add header not selectable in combobox item in C#?

I need create a custom combobox control that allows header as separator which should not be selectable using the mouse move or key press.

this is example:

Header1
  item1
  item2
  item3
Header2
  item4
  item5

I tried many solutions, without success. Thanks in advance!

like image 272
Vincenzo Lo Palo Avatar asked Oct 28 '25 09:10

Vincenzo Lo Palo


2 Answers

Once again, WPF can easily provide solutions that would require tons of horrible hacks in winforms.

Copy and paste my code in a File -> New Project -> WPF Application in Visual Studio.

You will quickly notice that my solution not only provides a different visual appearance for Header Items, but it also prevents unwanted selection, be it via mouse or keyboard, and it doesn't need to subclass the regular ComboBox class, which would lead to lesser maintainability.

ComboBox

XAML:

<Window x:Class="WpfApplication5.Window2"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApplication5"
        Title="Window2" Height="300" Width="300">
    <Grid>
        <ComboBox ItemsSource="{Binding}" DisplayMemberPath="DisplayText"
                  VerticalAlignment="Center" HorizontalAlignment="Center" 
                  Height="25" Width="100">
            <ComboBox.ItemContainerStyle>
                <Style TargetType="ComboBoxItem">
                    <Setter Property="Foreground" Value="Black"/>
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding IsHeader}" Value="True">
                            <Setter Property="IsEnabled" Value="False"/>
                            <Setter Property="FontWeight" Value="Bold"/>
                        </DataTrigger>
                        <DataTrigger Binding="{Binding IsHeader}" Value="False">
                            <Setter Property="Margin" Value="10,0,0,0"/>
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </ComboBox.ItemContainerStyle>
        </ComboBox>
    </Grid>
</Window>

Code Behind:

using System.Collections.Generic;
using System.Windows;

namespace WpfApplication5
{
    public partial class Window2 : Window
    {
        public Window2()
        {
            InitializeComponent();

            var list = new List<ComboBoxItem>
                {
                    new ComboBoxItem {DisplayText = "Header1", IsHeader = true},
                    new ComboBoxItem {DisplayText = "Item1", IsHeader = false},
                    new ComboBoxItem {DisplayText = "Item2", IsHeader = false},
                    new ComboBoxItem {DisplayText = "Item3", IsHeader = false},
                    new ComboBoxItem {DisplayText = "Header2", IsHeader = true},
                    new ComboBoxItem {DisplayText = "Item4", IsHeader = false},
                    new ComboBoxItem {DisplayText = "Item5", IsHeader = false},
                    new ComboBoxItem {DisplayText = "Item6", IsHeader = false},
                };

            DataContext = list;
        }
    }

    public class ComboBoxItem
    {
        public string DisplayText { get; set; }
        public bool IsHeader { get; set; }
    }
}
like image 107
Federico Berasategui Avatar answered Oct 30 '25 15:10

Federico Berasategui


Try this custom combo box. It ignores the header, but the header is drawn exactly like any other item and when you select a subitem, it will contain those extra spaces. But hopefully this leads you in the right direction.

public class CustomComboBox : ComboBox
{
    int currentlySelectedIndex = -1;

    protected override void OnSelectionChangeCommitted(EventArgs e)
    {
        if (this.SelectedIndex != -1)
        {
            // Check if we shouldn ignore it:
            object currentlySelectedItem = this.Items[this.SelectedIndex];

            if (ShouldIgnore(currentlySelectedItem))
            {
                Console.WriteLine("Ignoring it! Resetting the index.");

                this.SelectedIndex = currentlySelectedIndex;
            }
        }

        base.OnSelectionChangeCommitted(e);
    }

    protected virtual bool ShouldIgnore(object selectedItem)
    {
        // This is a category if it starts with a space. 
        return !selectedItem.ToString().StartsWith(" ");     
    }

    protected override void OnDropDown(EventArgs e)
    {
        // Save the current index when the drop down shows:
        currentlySelectedIndex = this.SelectedIndex;

        base.OnDropDown(e);
    }
}
like image 36
steinar Avatar answered Oct 30 '25 15:10

steinar



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!