Hi,@Reinder Weenink. Welcome to Microsoft Q&A.
It's difficult to create and style a ComboBox in C# code without using XAML.
You can customize the appearance and behavior of a ComboBox simply by modifying its properties and the ControlTemplate in code-behind. But when more attributes are involved, a lot of errors appear
It can be more verbose and less intuitive than defining styles and templates in XAML.
I tried copying styles from xaml to codebedhind without success.
my steps: create a ComboBox in xaml designer ->right click the ComboBox ->Select Edit Template->select Edit a Copy... ->select OK to ComboBoxStyle ->edit the generate style (Simplify the code regarding colors)->then try to realize the same effect in codebedhind
private void ApplyCustomComboBoxStyle()
{
// FocusVisual style
Style focusVisualStyle = new Style(typeof(Control));
focusVisualStyle.Setters.Add(new Setter(Control.TemplateProperty, new ControlTemplate(typeof(Control))));
Application.Current.Resources.Add(SystemColors.ControlTextBrushKey, Brushes.Black);
Application.Current.Resources.Add("FocusVisual", focusVisualStyle);
// ComboBoxEditableTextBox style
Style comboBoxEditableTextBoxStyle = new Style(typeof(TextBox));
comboBoxEditableTextBoxStyle.Setters.Add(new Setter(TextBox.OverridesDefaultStyleProperty, true));
comboBoxEditableTextBoxStyle.Setters.Add(new Setter(TextBox.AllowDropProperty, true));
comboBoxEditableTextBoxStyle.Setters.Add(new Setter(TextBox.MinWidthProperty, 0d));
comboBoxEditableTextBoxStyle.Setters.Add(new Setter(TextBox.MinHeightProperty, 0d));
comboBoxEditableTextBoxStyle.Setters.Add(new Setter(TextBox.FocusVisualStyleProperty, null));
//comboBoxEditableTextBoxStyle.Setters.Add(new Setter(TextBox.ScrollViewer.PanningModeProperty, PanningMode.VerticalFirst));
// comboBoxEditableTextBoxStyle.Setters.Add(new Setter(TextBox.StylusIsFlicksEnabledProperty, false));
comboBoxEditableTextBoxStyle.Setters.Add(new Setter(TextBox.TemplateProperty, new ControlTemplate(typeof(TextBox))));
// ComboBoxToggleButton style
Style comboBoxToggleButtonStyle = new Style(typeof(ToggleButton));
comboBoxToggleButtonStyle.Setters.Add(new Setter(ToggleButton.OverridesDefaultStyleProperty, true));
comboBoxToggleButtonStyle.Setters.Add(new Setter(ToggleButton.IsTabStopProperty, false));
comboBoxToggleButtonStyle.Setters.Add(new Setter(ToggleButton.FocusableProperty, false));
comboBoxToggleButtonStyle.Setters.Add(new Setter(ToggleButton.ClickModeProperty, ClickMode.Press));
comboBoxToggleButtonStyle.Setters.Add(new Setter(ToggleButton.TemplateProperty, CreateComboBoxToggleButtonTemplate()));
// ComboBoxTemplate
ControlTemplate comboBoxTemplate = CreateComboBoxTemplate();
Application.Current.Resources.Add("ComboBoxTemplate", comboBoxTemplate);
// ComboBoxStyle1
Style comboBoxStyle1 = new Style(typeof(ComboBox));
comboBoxStyle1.Setters.Add(new Setter(ComboBox.FocusVisualStyleProperty, Application.Current.Resources["FocusVisual"]));
comboBoxStyle1.Setters.Add(new Setter(ComboBox.BackgroundProperty, Brushes.Pink));
comboBoxStyle1.Setters.Add(new Setter(ComboBox.BorderBrushProperty, Brushes.Purple));
comboBoxStyle1.Setters.Add(new Setter(ComboBox.ForegroundProperty, SystemColors.WindowTextBrush));
comboBoxStyle1.Setters.Add(new Setter(ComboBox.BorderThicknessProperty, new Thickness(1)));
comboBoxStyle1.Setters.Add(new Setter(ScrollViewer.HorizontalScrollBarVisibilityProperty, ScrollBarVisibility.Auto));
comboBoxStyle1.Setters.Add(new Setter(ScrollViewer.VerticalScrollBarVisibilityProperty, ScrollBarVisibility.Auto));
comboBoxStyle1.Setters.Add(new Setter(ScrollViewer.CanContentScrollProperty, true));
comboBoxStyle1.Setters.Add(new Setter(ScrollViewer.PanningModeProperty, PanningMode.Both));
comboBoxStyle1.Setters.Add(new Setter(Stylus.IsFlicksEnabledProperty, false));
comboBoxStyle1.Setters.Add(new Setter(ComboBox.TemplateProperty, comboBoxTemplate));
// Apply style to ComboBox
ComboBox comboBox = new ComboBox();
comboBox.Style = comboBoxStyle1;
comboBox.Items.Add(new ComboBoxItem() { Content = "1" });
comboBox.Items.Add(new ComboBoxItem() { Content = "2" });
comboBox.Items.Add(new ComboBoxItem() { Content = "3" });
// Add ComboBox to the StackPanel
grid.Children.Add(comboBox);
}
private ControlTemplate CreateComboBoxToggleButtonTemplate()
{
ControlTemplate template = new ControlTemplate(typeof(ToggleButton));
FrameworkElementFactory border = new FrameworkElementFactory(typeof(Border));
border.Name = "templateRoot";
border.SetValue(Border.BackgroundProperty, Brushes.Red);
border.SetValue(Border.BorderBrushProperty, Brushes.Blue);
border.SetValue(Border.BorderThicknessProperty, new Thickness(1));
border.SetValue(Border.SnapsToDevicePixelsProperty, true);
FrameworkElementFactory splitBorder = new FrameworkElementFactory(typeof(Border));
splitBorder.SetValue(Border.BackgroundProperty, Brushes.Gray);
splitBorder.SetValue(Border.BorderBrushProperty, Brushes.Transparent);
splitBorder.SetValue(Border.BorderThicknessProperty, new Thickness(1));
splitBorder.SetValue(Border.HorizontalAlignmentProperty, HorizontalAlignment.Right);
splitBorder.SetValue(Border.MarginProperty, new Thickness(0));
splitBorder.SetValue(Border.SnapsToDevicePixelsProperty, true);
splitBorder.SetValue(Border.WidthProperty, SystemParameters.VerticalScrollBarWidth);
FrameworkElementFactory arrow = new FrameworkElementFactory(typeof(Path));
arrow.SetValue(Path.DataProperty, Geometry.Parse("F1 M 0,0 L 2.667,2.66665 L 5.3334,0 L 5.3334,-1.78168 L 2.6667,0.88501 L0,-1.78168 L0,0 Z"));
arrow.SetValue(Path.FillProperty, Brushes.Gray);
arrow.SetValue(Path.HorizontalAlignmentProperty, HorizontalAlignment.Center);
arrow.SetValue(Path.MarginProperty, new Thickness(0));
arrow.SetValue(Path.VerticalAlignmentProperty, VerticalAlignment.Center);
splitBorder.AppendChild(arrow);
border.AppendChild(splitBorder);
template.VisualTree = border;
return template;
}
private ControlTemplate CreateComboBoxTemplate()
{
ControlTemplate template = new ControlTemplate(typeof(ComboBox));
FrameworkElementFactory grid = new FrameworkElementFactory(typeof(Grid));
grid.Name = "templateRoot";
grid.SetValue(Grid.SnapsToDevicePixelsProperty, true);
FrameworkElementFactory popup = new FrameworkElementFactory(typeof(Popup));
popup.Name = "PART_Popup";
popup.SetValue(Popup.AllowsTransparencyProperty, true);
popup.SetValue(Popup.IsOpenProperty, new TemplateBindingExtension(ComboBox.IsDropDownOpenProperty));
popup.SetValue(Popup.MarginProperty, new Thickness(1));
popup.SetValue(Popup.PlacementProperty, PlacementMode.Bottom);
popup.SetValue(Popup.PopupAnimationProperty, SystemParameters.ComboBoxPopupAnimation);
// System.Windows.Controls.Primitives.SystemDropShadowChrome shadow = new System.Windows.Controls.Primitives.SystemDropShadowChrome();
// FrameworkElementFactory shadow = new FrameworkElementFactory(typeof(SystemDropShadowChrome));
// shadow.Name = "shadow";
// shadow.SetValue(SystemDropShadowChrome.ColorProperty, Colors.Transparent);
// shadow.SetValue(SystemDropShadowChrome.MinWidthProperty, new TemplateBindingExtension(grid.ActualWidthProperty));
// shadow.SetValue(SystemDropShadowChrome.MaxHeightProperty, new TemplateBindingExtension(ComboBox.MaxDropDownHeightProperty));
//FrameworkElementFactory dropDownBorder = new FrameworkElementFactory(typeof(Border));
//dropDownBorder.Name = "dropDownBorder";
//dropDownBorder.SetValue(Border.BackgroundProperty, SystemColors.WindowBrush);
//dropDownBorder.SetValue(Border.BorderBrushProperty, SystemColors.WindowFrameBrush);
//dropDownBorder.SetValue(Border.BorderThicknessProperty, new Thickness(1));
// FrameworkElementFactory dropDownScrollViewer = new FrameworkElementFactory(typeof(ScrollViewer));
// dropDownScrollViewer.Name = "DropDownScrollViewer";
FrameworkElementFactory itemsPresenter = new FrameworkElementFactory(typeof(ItemsPresenter));
itemsPresenter.Name = "ItemsPresenter";
itemsPresenter.SetValue(KeyboardNavigation.DirectionalNavigationProperty, KeyboardNavigationMode.Contained);
itemsPresenter.SetValue(UIElement.SnapsToDevicePixelsProperty, new TemplateBindingExtension(UIElement.SnapsToDevicePixelsProperty));
// dropDownScrollViewer.AppendChild(itemsPresenter);
// dropDownBorder.AppendChild(dropDownScrollViewer);
// shadow.AppendChild(dropDownBorder);
// popup.AppendChild(shadow);
grid.AppendChild(popup);
FrameworkElementFactory toggleButton = new FrameworkElementFactory(typeof(ToggleButton));
toggleButton.Name = "toggleButton";
toggleButton.SetValue(ToggleButton.BackgroundProperty, new TemplateBindingExtension(ComboBox.BackgroundProperty));
toggleButton.SetValue(ToggleButton.BorderBrushProperty, new TemplateBindingExtension(ComboBox.BorderBrushProperty));
toggleButton.SetValue(ToggleButton.BorderThicknessProperty, new TemplateBindingExtension(ComboBox.BorderThicknessProperty));
toggleButton.SetValue(ToggleButton.IsCheckedProperty, new Binding("IsDropDownOpen") { RelativeSource = new RelativeSource(RelativeSourceMode.TemplatedParent) });
toggleButton.SetValue(ToggleButton.StyleProperty, new StaticResourceExtension("ComboBoxToggleButton"));
grid.AppendChild(toggleButton);
FrameworkElementFactory contentPresenter = new FrameworkElementFactory(typeof(ContentPresenter));
contentPresenter.Name = "contentPresenter";
contentPresenter.SetValue(ContentPresenter.ContentStringFormatProperty, new TemplateBindingExtension(ComboBox.SelectionBoxItemStringFormatProperty));
contentPresenter.SetValue(ContentPresenter.ContentTemplateProperty, new TemplateBindingExtension(ComboBox.SelectionBoxItemTemplateProperty));
contentPresenter.SetValue(ContentPresenter.ContentProperty, new TemplateBindingExtension(ComboBox.SelectionBoxItemProperty));
contentPresenter.SetValue(ContentPresenter.ContentTemplateSelectorProperty, new TemplateBindingExtension(ComboBox.ItemTemplateSelectorProperty));
contentPresenter.SetValue(FrameworkElement.HorizontalAlignmentProperty, new TemplateBindingExtension(Control.HorizontalContentAlignmentProperty));
contentPresenter.SetValue(FrameworkElement.MarginProperty, new TemplateBindingExtension(Control.PaddingProperty));
contentPresenter.SetValue(FrameworkElement.SnapsToDevicePixelsProperty, new TemplateBindingExtension(UIElement.SnapsToDevicePixelsProperty));
contentPresenter.SetValue(FrameworkElement.VerticalAlignmentProperty, new TemplateBindingExtension(Control.VerticalContentAlignmentProperty));
grid.AppendChild(contentPresenter);
template.VisualTree = grid;
//Trigger hasDropShadowTrigger = new Trigger() { Property = ComboBox.HasDropShadowProperty, Value = true };
//hasDropShadowTrigger.Setters.Add(new Setter(Control.MarginProperty, new Thickness(0, 0, 5, 5)) { TargetName = "shadow" });
//hasDropShadowTrigger.Setters.Add(new Setter(SystemDropShadowChrome.ColorProperty, "#71000000") { TargetName = "shadow" });
//template.Triggers.Add(hasDropShadowTrigger);
//Trigger hasItemsTrigger = new Trigger() { Property = ItemsControl.HasItemsProperty, Value = false };
//hasItemsTrigger.Setters.Add(new Setter(FrameworkElement.HeightProperty, 95d) { TargetName = "dropDownBorder" });
//template.Triggers.Add(hasItemsTrigger);
MultiTrigger isGroupingTrigger = new MultiTrigger();
isGroupingTrigger.Conditions.Add(new Condition(ItemsControl.IsGroupingProperty, true));
isGroupingTrigger.Conditions.Add(new Condition(VirtualizingPanel.IsVirtualizingWhenGroupingProperty, false));
// isGroupingTrigger.Setters.Add(new Setter(ScrollViewer.CanContentScrollProperty, false) { TargetName = "DropDownScrollViewer" });
template.Triggers.Add(isGroupingTrigger);
// Trigger canContentScrollTrigger = new Trigger() { Property = ScrollViewer.CanContentScrollProperty, SourceName = "DropDownScrollViewer", Value = false };
// canContentScrollTrigger.Setters.Add(new Setter(Canvas.TopProperty, new Binding("VerticalOffset") { ElementName = "DropDownScrollViewer" }) { TargetName = "opaqueRect" });
// canContentScrollTrigger.Setters.Add(new Setter(Canvas.LeftProperty, new Binding("HorizontalOffset") { ElementName = "DropDownScrollViewer" }) { TargetName = "opaqueRect" });
// template.Triggers.Add(canContentScrollTrigger);
return template;
}
public void CustomComboBox()
{
// Create a style for the ComboBox
Style comboBoxStyle = new Style(typeof(ComboBox));
// Setters for various properties of the ComboBox
comboBoxStyle.Setters.Add(new Setter(BackgroundProperty, Brushes.LightGray));
comboBoxStyle.Setters.Add(new Setter(BorderBrushProperty, Brushes.Gray));
comboBoxStyle.Setters.Add(new Setter(BorderThicknessProperty, new Thickness(1)));
comboBoxStyle.Setters.Add(new Setter(ForegroundProperty, Brushes.Black));
// Create a ControlTemplate for the ComboBox
ControlTemplate comboBoxTemplate = new ControlTemplate(typeof(ComboBox));
// Create the main Grid in the ControlTemplate
FrameworkElementFactory gridFactory = new FrameworkElementFactory(typeof(Grid));
// Create the ToggleButton for the ComboBox
FrameworkElementFactory toggleButtonFactory = new FrameworkElementFactory(typeof(ToggleButton));
toggleButtonFactory.SetValue(ToggleButton.BackgroundProperty, Brushes.Transparent);
toggleButtonFactory.SetValue(ToggleButton.BorderThicknessProperty, new Thickness(0));
toggleButtonFactory.SetValue(ToggleButton.TemplateProperty, GetCustomToggleButtonTemplate());
// Add the ToggleButton to the main Grid
gridFactory.AppendChild(toggleButtonFactory);
// Set the ControlTemplate's VisualTree
comboBoxTemplate.VisualTree = gridFactory;
// Set the ComboBox's ControlTemplate
comboBoxStyle.Setters.Add(new Setter(TemplateProperty, comboBoxTemplate));
// Set the style to the ComboBox
this.Style = comboBoxStyle;
}
private ControlTemplate GetCustomToggleButtonTemplate()
{
// Create a ControlTemplate for the ToggleButton
ControlTemplate toggleButtonTemplate = new ControlTemplate(typeof(ToggleButton));
// Create the main Grid in the ControlTemplate
FrameworkElementFactory gridFactory = new FrameworkElementFactory(typeof(Grid));
// Set the Grid's properties
// Create the Border for the ToggleButton
FrameworkElementFactory borderFactory = new FrameworkElementFactory(typeof(Border));
borderFactory.SetValue(Border.BackgroundProperty, Brushes.Transparent);
borderFactory.SetValue(Border.BorderThicknessProperty, new Thickness(0));
// Create the ContentPresenter for the ToggleButton
FrameworkElementFactory contentPresenterFactory = new FrameworkElementFactory(typeof(ContentPresenter));
// Add the ContentPresenter to the Border
borderFactory.AppendChild(contentPresenterFactory);
// Add the Border to the main Grid
gridFactory.AppendChild(borderFactory);
// Set the ControlTemplate's VisualTree
toggleButtonTemplate.VisualTree = gridFactory;
return toggleButtonTemplate;
}
It is recommended to use xaml code and c# to set styles and templates.
If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".
Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.