none
change combobox items foreground color RRS feed

  • Question

  • Hi All.

    My WPF detail form has ComboBox with list of employees. And I would like when I open that form of according employee foreground ComboBox item for employees of that department have Green color and other ComboBox item have foreground color Gray. Is it possible to do that? If yes. How it to do?

    Thanks


    • Edited by zleug Friday, October 25, 2013 1:02 AM
    Friday, October 25, 2013 12:46 AM

Answers

  • Hello,

    I've took a lot of time to implement this, we can use a DataTrigger with MultiConverter:

    In MainWindow, we can choose a Department, click the button, the value will be passed to DetailWindow:

    <ComboBox Margin="5" Name="cmbDep" VerticalAlignment="Top" Width="100" Height="25" ItemsSource="{Binding}" />
    <Button Content="Open Detail" Height="40" Width="100" Click="Button_Click" />
    public MainWindow()
    {
                InitializeComponent();
    
                List<string> data= new List<string>() { "AAA", "BBB", "CCC", "DDD" };
                this.cmbDep.DataContext = data;
    }
    
    private void Button_Click(object sender, RoutedEventArgs e)
    {
                if (this.cmbDep.SelectedIndex != -1)
                {
                    DetailWindow w = new DetailWindow(this.cmbDep.SelectedValue.ToString());
                    w.Show();
                    this.Close();
                }
                else
                {
                    MessageBox.Show("Please select a value");
                }
    }

    In DetailWindow, it can get the value passed from MainWindow, when user click the employee ComboBox, the Conventer will compare each item's Department to the selected Department:

    <Window.Resources>
            <local:Converter x:Key="converter" />
        </Window.Resources>
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="50" />
                <RowDefinition />
            </Grid.RowDefinitions>
            <Label Content="Selected Department: " Grid.Row="0" />
            <Label Name="label" Margin="120,0,0,0" Grid.Row="0" />
            <ComboBox ItemsSource="{Binding}" Grid.Row="1" DisplayMemberPath="Name" VerticalAlignment="Top" Width="100" Height="25" SelectedIndex="0" >
                <ComboBox.ItemContainerStyle>
                    <Style TargetType="ComboBoxItem">
                        <Setter Property="Foreground" Value="Gray" />
    
                        <Style.Triggers>
                            <DataTrigger Value="true">
                                <DataTrigger.Binding>
                                    <MultiBinding Converter="{StaticResource converter}">
                                        <Binding Path="."/>
                                        <Binding ElementName="label" Path="Content" />
                                    </MultiBinding>
                                </DataTrigger.Binding>
                                <Setter Property="Foreground" Value="Green"/>
                                <Setter Property="FontWeight" Value="Bold" />
                            </DataTrigger>
                        </Style.Triggers>
                    </Style>
                </ComboBox.ItemContainerStyle>
            </ComboBox>
        </Grid>
    
    public partial class DetailWindow : Window
    {
            private ObservableCollection<Employee> data = new ObservableCollection<Employee>();
    
            public DetailWindow()
            {
                InitializeComponent();
            }
    
            public DetailWindow(string parameter) : this()
            {
                this.label.Content = parameter;
                
                data.Add(new Employee() { Name = "Anna", Department = "AAA" });
                data.Add(new Employee() { Name = "John", Department = "AAA" });
                data.Add(new Employee() { Name = "Smith", Department = "AAA" });
                data.Add(new Employee() { Name = "Pol", Department = "BBB" });
                data.Add(new Employee() { Name = "Gen", Department = "CCC" });
                data.Add(new Employee() { Name = "Cris", Department = "CCC" });
                data.Add(new Employee() { Name = "Bill", Department = "DDD" });
    
                this.DataContext = data;
            }
    }
    
    class Converter : IMultiValueConverter
    {
            public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
            {
                string value = ((Employee)values[0]).Department;
                string selectedvalue = values[1] as string;
    
                if (!string.IsNullOrEmpty(selectedvalue))
                {
                    string department = selectedvalue;
                    return value.Equals(department);
                }
    
                return false;
            }
    
            public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
            {
                throw new NotImplementedException();
            }
    }
    
    public class Employee
    {
            string name;
            string department;
    
            public string Name
            {
                get { return name; }
                set { name = value; }
            }
    
            public string Department
            {
                get { return department; }
                set { department = value; }
            }
    }

    Download Link:
    http://sdrv.ms/1busEx0


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    • Marked as answer by zleug Tuesday, October 29, 2013 2:53 PM
    Monday, October 28, 2013 9:39 AM
    Moderator

All replies

  • Hi zleug,

    I think you can use different styles for ComboBoxItem:

    <Window.Resources>
            <Style x:Key="MyComboxItem1" TargetType="{x:Type ComboBoxItem}">
                <Setter Property="Background" Value="Gray" />
            </Style>
            
            <Style x:Key="MyComboBox1" TargetType="{x:Type ComboBox}">
                <Setter Property="ItemContainerStyle" Value="{StaticResource MyComboxItem1}"/>
            </Style>
    
            <Style x:Key="MyComboxItem2" TargetType="{x:Type ComboBoxItem}">
                <Setter Property="Background" Value="Green" />
            </Style>
    
            <Style x:Key="MyComboBox2" TargetType="{x:Type ComboBox}">
                <Setter Property="ItemContainerStyle" Value="{StaticResource MyComboxItem2}"/>
            </Style>
    </Window.Resources>

    MyComboBox1 style can set the ComboBoxItem's background to Green and MyComboBox2 can change it to Gray.

    How to use these styles:

    <DataGrid Margin="5" ItemsSource="{Binding}" AutoGenerateColumns="False">
                    <DataGrid.Columns>
                        <DataGridTemplateColumn Header="Cities" Width="*">
                            <DataGridTemplateColumn.CellTemplate>
                                <DataTemplate>
                                <ComboBox Margin="2" ItemsSource="{Binding Cities}" Style="{StaticResource MyComboBox2}" />
                            </DataTemplate>
                            </DataGridTemplateColumn.CellTemplate>
                        </DataGridTemplateColumn>
                    <DataGridTemplateColumn Header="TestColumn" Width="*">
                        <DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <ComboBox Margin="2" ItemsSource="{Binding TestColumn}" Style="{StaticResource MyComboBox1}" />
                            </DataTemplate>
                        </DataGridTemplateColumn.CellTemplate>
                    </DataGridTemplateColumn>
                </DataGrid.Columns>
    </DataGrid>

    >>I would like when I open that form of according employee foreground ComboBox item for employees of that department have Green color and other ComboBox item have foreground color Gray

    Because other ComboBox item have foreground color Gray, so you can also use a "global" style to set background to gray:

    <Style TargetType="ComboBoxItem">
                <Setter Property="Background" Value="Gray" />
    </Style>

    Then set the style of department combobox separately: Style="{StaticResource MyComboBox2}"

    You can download my sample from Skydrive:
    http://sdrv.ms/1c24E5d


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Friday, October 25, 2013 4:33 AM
    Moderator
  • Hi Franklin. Thanks for replay.

    My detail form I have one ComboBox with list of employees from different departments. For instance, the combobox has list of employees:

    Anna - AAA
    John  - AAA
    Smith - AAA
    Pol     - BBB
    Gen    - CCC
    Cris    - CCC
    Bill      - DDD.
    Those employee from departments: AAA, BBB, CCC, DDD. In case I selected from main form employee Anna from department AAA and open detail form. In that case I would like all employees from department AAA in ComboBox will have foreground Green and rest employees in that list foreground Gray. If I will select employee Gen from depertmant CCC the ComboBox item related to department CCC will have foreground Green and rest foreground Gray. Is it possible to do? If yes. How to do it?

    Thanks.

    Friday, October 25, 2013 2:28 PM
  • You could use trigger with a DataBinding in the Style for the ComboBoxItem that uses a MultiConverter to return a value based on the comparison of the string in the ComboBox and the selected value:

        <ComboBox x:Name="comboBox" xmlns:local="clr-namespace:WpfApplication1">
          <ComboBox.Resources>
            <local:Converter x:Key="converter"/>
            <Style TargetType="ComboBoxItem">
              <Setter Property="Foreground" Value="Gray"/>
              <Style.Triggers>
                <DataTrigger Value="true">
                  <DataTrigger.Binding>
                    <MultiBinding Converter="{StaticResource converter}">
                      <Binding Path="."/>
                      <Binding Path="SelectedValue" RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType=ComboBox}"/>
                    </MultiBinding>
                  </DataTrigger.Binding>
                  <Setter Property="Foreground" Value="Green"/>
                </DataTrigger>
              </Style.Triggers>
            </Style>
          </ComboBox.Resources>
        </ComboBox>

          comboBox.ItemsSource = new List<string>()
          {
            "Anna - AAA",
             "John - AAA",
             "Smith - AAA",
             "Pol - BBB",
             "Gen - CCC",
             "Cris - CCC",
             "Bill - DDD" 
          };
    
      class Converter : IMultiValueConverter
      {
        public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
          string value = values[0] as string;
          string selectedvalue = values[1] as string;
    
          if (!string.IsNullOrEmpty(selectedvalue)) {
            string department = selectedvalue.Substring(selectedvalue.Length - 3, 3);
            return value.Substring(value.Length - 3, 3).Equals(department);
          }
    
          return false;
        }
    
        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture) {
          throw new NotImplementedException();
        }
      }

    Friday, October 25, 2013 3:41 PM
  • Hello,

    If the struct of Employee is like this:

    public class Employee
    {
            string name;
            string department;
    
            public string Name
            {
                get{ return name; }
                set{ name=value; }
            }
    
            public string Department
            {
                get{ return department; }
                set { department = value; }
            }
    }

    You can use DataTrigger to change Background Color:

    <ComboBox Margin="2" ItemsSource="{Binding}" DisplayMemberPath="Name" VerticalAlignment="Top" Width="100" Height="30" >
                <ComboBox.ItemContainerStyle>
                    <Style TargetType="ComboBoxItem">
                        <Setter Property="Foreground" Value="Gray" />
                        <Style.Triggers>
                            <DataTrigger Binding="{Binding Department}" Value="AAA">
                                <Setter Property="Foreground" Value="Green" />
                            </DataTrigger>
                        </Style.Triggers>
                    </Style>
                </ComboBox.ItemContainerStyle>
            </ComboBox>


    New Project download link:
    http://sdrv.ms/1aq3eT3


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Friday, October 25, 2013 4:28 PM
    Moderator
  • Hi Franclin. That is very interesting.

    But in your code foreground color is hard-coded for binding Department I would like that foreground color will change depends from selected employee. If in main form was selected employee from AAA department, in opened detail form foreground color of ComboBox items of AAA department will be Green and rest will be Gray.  If in main form selected employee from BBB department, in opened detail form foreground color of ComboBox items of BBB department will be Green and rest will be Gray and so on. Is it possible to change foreground color programmatically?

    Thanks.


    • Edited by zleug Saturday, October 26, 2013 3:48 PM
    Saturday, October 26, 2013 3:42 PM
  • Hello,

    I've took a lot of time to implement this, we can use a DataTrigger with MultiConverter:

    In MainWindow, we can choose a Department, click the button, the value will be passed to DetailWindow:

    <ComboBox Margin="5" Name="cmbDep" VerticalAlignment="Top" Width="100" Height="25" ItemsSource="{Binding}" />
    <Button Content="Open Detail" Height="40" Width="100" Click="Button_Click" />
    public MainWindow()
    {
                InitializeComponent();
    
                List<string> data= new List<string>() { "AAA", "BBB", "CCC", "DDD" };
                this.cmbDep.DataContext = data;
    }
    
    private void Button_Click(object sender, RoutedEventArgs e)
    {
                if (this.cmbDep.SelectedIndex != -1)
                {
                    DetailWindow w = new DetailWindow(this.cmbDep.SelectedValue.ToString());
                    w.Show();
                    this.Close();
                }
                else
                {
                    MessageBox.Show("Please select a value");
                }
    }

    In DetailWindow, it can get the value passed from MainWindow, when user click the employee ComboBox, the Conventer will compare each item's Department to the selected Department:

    <Window.Resources>
            <local:Converter x:Key="converter" />
        </Window.Resources>
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="50" />
                <RowDefinition />
            </Grid.RowDefinitions>
            <Label Content="Selected Department: " Grid.Row="0" />
            <Label Name="label" Margin="120,0,0,0" Grid.Row="0" />
            <ComboBox ItemsSource="{Binding}" Grid.Row="1" DisplayMemberPath="Name" VerticalAlignment="Top" Width="100" Height="25" SelectedIndex="0" >
                <ComboBox.ItemContainerStyle>
                    <Style TargetType="ComboBoxItem">
                        <Setter Property="Foreground" Value="Gray" />
    
                        <Style.Triggers>
                            <DataTrigger Value="true">
                                <DataTrigger.Binding>
                                    <MultiBinding Converter="{StaticResource converter}">
                                        <Binding Path="."/>
                                        <Binding ElementName="label" Path="Content" />
                                    </MultiBinding>
                                </DataTrigger.Binding>
                                <Setter Property="Foreground" Value="Green"/>
                                <Setter Property="FontWeight" Value="Bold" />
                            </DataTrigger>
                        </Style.Triggers>
                    </Style>
                </ComboBox.ItemContainerStyle>
            </ComboBox>
        </Grid>
    
    public partial class DetailWindow : Window
    {
            private ObservableCollection<Employee> data = new ObservableCollection<Employee>();
    
            public DetailWindow()
            {
                InitializeComponent();
            }
    
            public DetailWindow(string parameter) : this()
            {
                this.label.Content = parameter;
                
                data.Add(new Employee() { Name = "Anna", Department = "AAA" });
                data.Add(new Employee() { Name = "John", Department = "AAA" });
                data.Add(new Employee() { Name = "Smith", Department = "AAA" });
                data.Add(new Employee() { Name = "Pol", Department = "BBB" });
                data.Add(new Employee() { Name = "Gen", Department = "CCC" });
                data.Add(new Employee() { Name = "Cris", Department = "CCC" });
                data.Add(new Employee() { Name = "Bill", Department = "DDD" });
    
                this.DataContext = data;
            }
    }
    
    class Converter : IMultiValueConverter
    {
            public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
            {
                string value = ((Employee)values[0]).Department;
                string selectedvalue = values[1] as string;
    
                if (!string.IsNullOrEmpty(selectedvalue))
                {
                    string department = selectedvalue;
                    return value.Equals(department);
                }
    
                return false;
            }
    
            public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
            {
                throw new NotImplementedException();
            }
    }
    
    public class Employee
    {
            string name;
            string department;
    
            public string Name
            {
                get { return name; }
                set { name = value; }
            }
    
            public string Department
            {
                get { return department; }
                set { department = value; }
            }
    }

    Download Link:
    http://sdrv.ms/1busEx0


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    • Marked as answer by zleug Tuesday, October 29, 2013 2:53 PM
    Monday, October 28, 2013 9:39 AM
    Moderator
  • Hi Franklin. Thanks a lot. That is awesome.
    Tuesday, October 29, 2013 2:34 AM
  • You're welcome, please mark some answers ;)

    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    • Marked as answer by zleug Tuesday, October 29, 2013 2:52 PM
    • Unmarked as answer by zleug Tuesday, October 29, 2013 2:53 PM
    Tuesday, October 29, 2013 3:29 AM
    Moderator