Styling WPF ComboBox items
Asked Answered
D

2

19

I have a very simple WPF application which displays a ComboBox which binds to a list of classes which represent people. Each 'Person' object has a Name string field, and a Sex enum. I would like the ComboBox to display a drop-down of the various people's Name field, but for each line to be styled according to the Sex field, for example, blue for males, pink for females. Can anyone tell me what I am doing wrong?

Here is the XML:

<Window x:Class="ComboBoxColour.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <StackPanel Orientation="Vertical">
        <ComboBox ItemsSource="{Binding People}" Width="100" Height="20">
            <ComboBox.ItemTemplate>
                <DataTemplate>
                    <TextBlock Name="somePerson" Text="{Binding Path=Name}">                        
                        <TextBlock.Triggers>
                            <DataTrigger Binding="{Binding Path=Sex}" Value="Male">
                                <DataTrigger.Setters>
                                    <Setter Property="Foreground" Value="Blue" TargetName="somePerson" />
                                </DataTrigger.Setters>
                            </DataTrigger>
                        </TextBlock.Triggers>                        
                    </TextBlock>
                </DataTemplate>
            </ComboBox.ItemTemplate>
        </ComboBox>
    </StackPanel>
</Window>

And here is the C#:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Collections.ObjectModel;

namespace ComboBoxColour
{
  /// <summary>
  /// Interaction logic for MainWindow.xaml
  /// </summary>
  public partial class MainWindow : Window
  {
    public List<Person> people;
    public List<Person> People
    {
      get { return people; }
      set { people = value; }
    }

    public MainWindow()
    {
      this.DataContext = this;

      People = new List<Person>();
      People.Add(new Person("Alice", SexEnum.Female));
      People.Add(new Person("Bob", SexEnum.Male));
      People.Add(new Person("Claire", SexEnum.Female));
      People.Add(new Person("Daniel", SexEnum.Male));

      InitializeComponent();
    }
  }

  public enum SexEnum{Male,Female};

  public class Person
  {
    private string name;
    public string Name
    {
      get { return name; }
      set { name = value; }
    }

    private SexEnum sex;
    public SexEnum Sex
    {
      get { return sex; }
      set { sex = value; }
    }

    public Person(string Name, SexEnum Sex)
    {
      this.Name = Name;
      this.Sex = Sex;
    }
  }
}

Many thanks in advance

Dissected answered 5/1, 2012 at 16:49 Comment(0)
I
22

You should use "Style" triggers instead of "TextBlock.Triggers"

use this XAML:

<Window x:Class="ComboBoxColour.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <StackPanel Orientation="Vertical">
        <ComboBox ItemsSource="{Binding People}" Width="100" Height="20">
            <ComboBox.ItemTemplate>
                <DataTemplate>
                    <TextBlock Name="somePerson" Text="{Binding Path=Name}">
                        <TextBlock.Style>
                            <Style TargetType="TextBlock">
                                <Style.Triggers>
                                    <DataTrigger Binding="{Binding Path=Sex}" Value="Male">
                                        <DataTrigger.Setters>
                                            <Setter Property="Foreground" Value="blue"/>
                                        </DataTrigger.Setters>
                                    </DataTrigger>
                                    <DataTrigger Binding="{Binding Path=Sex}" Value="Female">
                                        <DataTrigger.Setters>
                                            <Setter Property="Foreground" Value="Pink"/>
                                        </DataTrigger.Setters>
                                    </DataTrigger>
                                </Style.Triggers>
                            </Style>
                        </TextBlock.Style>
                    </TextBlock>
                </DataTemplate>
            </ComboBox.ItemTemplate>
        </ComboBox>
    </StackPanel>
</Window>

Now you'll have blue for male and pink for female.

Inurbane answered 5/1, 2012 at 17:8 Comment(0)
I
30

Use ItemContainerStyle instead of ItemTemplate:

    <ComboBox ItemsSource="{Binding People}" Width="100" Height="20">
        <ComboBox.ItemContainerStyle>
            <Style TargetType="ComboBoxItem">
                <Setter Property="Foreground" Value="Pink" />
                <Style.Triggers>
                    <DataTrigger Binding="{Binding Path=Sex}" Value="Male">
                        <Setter Property="Foreground" Value="Blue" />
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </ComboBox.ItemContainerStyle>
    </ComboBox>
Illona answered 5/1, 2012 at 17:10 Comment(0)
I
22

You should use "Style" triggers instead of "TextBlock.Triggers"

use this XAML:

<Window x:Class="ComboBoxColour.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <StackPanel Orientation="Vertical">
        <ComboBox ItemsSource="{Binding People}" Width="100" Height="20">
            <ComboBox.ItemTemplate>
                <DataTemplate>
                    <TextBlock Name="somePerson" Text="{Binding Path=Name}">
                        <TextBlock.Style>
                            <Style TargetType="TextBlock">
                                <Style.Triggers>
                                    <DataTrigger Binding="{Binding Path=Sex}" Value="Male">
                                        <DataTrigger.Setters>
                                            <Setter Property="Foreground" Value="blue"/>
                                        </DataTrigger.Setters>
                                    </DataTrigger>
                                    <DataTrigger Binding="{Binding Path=Sex}" Value="Female">
                                        <DataTrigger.Setters>
                                            <Setter Property="Foreground" Value="Pink"/>
                                        </DataTrigger.Setters>
                                    </DataTrigger>
                                </Style.Triggers>
                            </Style>
                        </TextBlock.Style>
                    </TextBlock>
                </DataTemplate>
            </ComboBox.ItemTemplate>
        </ComboBox>
    </StackPanel>
</Window>

Now you'll have blue for male and pink for female.

Inurbane answered 5/1, 2012 at 17:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.