Is it possible to create and set styles and/or template for combobox in c# only?

Reinder Weenink 20 Reputation points
2024-04-12T14:03:37.46+00:00

Hi,

I'm trying to setup a app frontend in C# only. I'm more practiced with c# then XAML, but also have the feeling that I can make the app windows/pages more parametric in this way.

Thus far I'm succeeding in this, however when I tried setting up comboboxes in this way I encountered problems which I dont understand and cant find info over.

Is it possible to setup custom combobox styles/visuals in c# only?

If yes, is there documentation or any samples for this?

Below a hyperlink to a website of microsoft with samples in XAML to give an idea of the things i would like to setup.

Shape,

background color,

selecteditem color,

etc.

https://learn.microsoft.com/en-us/dotnet/desktop/wpf/controls/how-to-create-apply-template?view=netdesktop-8.0

Thanks in advance, Kind regards.

Windows Presentation Foundation
Windows Presentation Foundation
A part of the .NET Framework that provides a unified programming model for building line-of-business desktop applications on Windows.
2,784 questions
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
11,015 questions
0 comments No comments
{count} votes

Accepted answer
  1. Hui Liu-MSFT 48,571 Reputation points Microsoft Vendor
    2024-04-15T07:45:14.6333333+00:00

    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.


0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.