问题
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!
回答1:
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.

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; }
}
}
回答2:
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);
}
}
来源:https://stackoverflow.com/questions/14866064/windows-form-how-add-header-not-selectable-in-combobox-item-in-c