Changing the Background color of some ListBox Items

mauede 221 Reputation points
2022-04-14T14:32:04.68+00:00

The ListBox is defined as follows:

 <ListBox x:Name="EditableStructs" Grid.Row="5" Grid.Column="1" Margin="930,62,0,40"  SelectionMode="Single"  Grid.ColumnSpan="2" Background="PowderBlue" Height="500"
                           ScrollViewer.VerticalScrollBarVisibility="Visible" ScrollViewer.CanContentScroll="True"  ItemsSource="{Binding AutoNames,Mode=TwoWay}" HorizontalAlignment="Left" Width="220"  >
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="Auto"/>
                            <ColumnDefinition Width="Auto"/>
                            <ColumnDefinition Width="*"/>
                        </Grid.ColumnDefinitions>
                        <TextBlock Name="TextInd" Text="{Binding NamInd, Mode=OneWay}"  Grid.Column="0" Padding="1,5" HorizontalAlignment="Stretch"/>
                        <CheckBox IsChecked="{Binding IsAccepted, Mode=TwoWay}" Grid.Column="1"  Padding="5,5" VerticalAlignment="Center" HorizontalAlignment="Center"  />
                        <TextBox Text="{Binding  StrName, Mode=TwoWay}"  Background="{Binding MyBackground}"  Grid.Column="2" HorizontalAlignment="Stretch"/>
                    </Grid>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>

The number of items as well as which items should have a different colour is known at runtime when the strings to be displayed are being generated.

foreach (string str in EditedList)
            {
                AutoNames.Add(new EditableStructures { StrName = str,  IsAccepted = false, NamInd = j});
                j++;
            }

EditableStructs.ItemsSource = (System.Collections.IEnumerable)AutoNames;

Clearly indexing the ListBox makes sense after the ListBox has been generated.
My problem is to select programmatically the ListBox items whose colour is to be changed:
I tried the following:

for(int i =0; i < EditableStructs.Items.Count; i++)
            {
                if (IsGuessed[i])
                    EditableStructs.TextBox[i].Background = "Red";
            }

But it does not work even if I replace TextBox with Items

I would appreciate any kind of help. Thank you in advance

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,783 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,005 questions
{count} votes

Accepted answer
  1. Hui Liu-MSFT 48,571 Reputation points Microsoft Vendor
    2022-04-18T09:46:36.293+00:00

    You could try to refer the following code to your project.
    MainWindow.xaml:

     <StackPanel>  
            <ListBox x:Name="EditableStructs"   SelectionMode="Single" Width="400"  Background="PowderBlue" Height="300"  
                                 ScrollViewer.VerticalScrollBarVisibility="Visible" ScrollViewer.CanContentScroll="True"   
                      ItemsSource="{Binding AutoNames,Mode=TwoWay}"  >  
      
                <ListBox.ItemTemplate>  
                    <DataTemplate>  
                        <Grid x:Name="grid">  
                            <Grid.ColumnDefinitions>  
                                <ColumnDefinition Width="Auto"/>  
                                <ColumnDefinition Width="Auto"/>  
                                <ColumnDefinition Width="*"/>  
                            </Grid.ColumnDefinitions>  
                            <TextBlock Name="TextInd" Text="{Binding NamInd, Mode=OneWay}"  Grid.Column="0" Padding="1,5" HorizontalAlignment="Stretch"/>  
                            <CheckBox IsChecked="{Binding IsAccepted, Mode=TwoWay}" Grid.Column="1"  Padding="5,5" VerticalAlignment="Center" HorizontalAlignment="Center"  />  
                            <TextBox x:Name="tb" Text="{Binding  StrName, Mode=TwoWay}"  Background="{Binding MyBackground}"  Grid.Column="2" HorizontalAlignment="Stretch"/>  
                        </Grid>  
                    </DataTemplate>  
                </ListBox.ItemTemplate>  
            </ListBox>  
            <Button x:Name="btn" Content="change" Click="btn_Click"/>  
        </StackPanel>  
    

    MainWindow.xaml.cs:

    using System.Collections.Generic;  
    using System.Collections.ObjectModel;  
    using System.ComponentModel;  
    using System.Windows;  
    using System.Windows.Controls;  
    using System.Windows.Media;  
      
    namespace ListBoxBackgroundDynamicallySet  
    {  
      public partial class MainWindow : Window  
      {  
        public ObservableCollection<EditableStructures> AutoNames { get; set; }  
        public List<string> EditedList = new List<string>() { "name1", "name2", "name3", "name4", "name5", "name6" };  
        int j = 0;  
        public MainWindow()  
        {  
          InitializeComponent();  
          AutoNames = new ObservableCollection<EditableStructures>();  
          DataContext = this;  
          foreach (string str in EditedList)  
          {  
            if (j % 3 == 0)  
            {  
              AutoNames.Add(new EditableStructures { StrName = str, IsAccepted = false, NamInd = j, SpecialFeatures = SpecialFeatures.Highlight , IsGuessed=false });  
            }  
            else if (j % 3 == 1)  
            {  
              AutoNames.Add(new EditableStructures { StrName = str, IsAccepted = true, NamInd = j, SpecialFeatures = SpecialFeatures.Color,IsGuessed = true });  
            }  
            else  
            {  
              AutoNames.Add(new EditableStructures { StrName = str, IsAccepted = false, NamInd = j, SpecialFeatures = SpecialFeatures.None, IsGuessed = false });  
            }  
            j++;  
          }  
      
          EditableStructs.ItemsSource = (System.Collections.IEnumerable)AutoNames;  
        }  
        List<bool> IsGuessed = new List<bool>() { true, false, true, true, false, false };  
         private void btn_Click(object sender, RoutedEventArgs e)  
    {  
      for (int i = 0; i < EditableStructs.Items.Count; i++)  
      {  
    
        if (IsGuessed[i])  
        {  
          TextBox gg = FindDescendant<TextBox>(EditableStructs.ItemContainerGenerator.ContainerFromIndex(i) as ListBoxItem);  
          gg.Background= Brushes.Red;   
        }  
        else  
        {  
          TextBox gg = FindDescendant<TextBox>(EditableStructs.ItemContainerGenerator.ContainerFromIndex(i) as ListBoxItem);  
          gg.Background = Brushes.White;  
        }  
      }  
    }  
        public T FindDescendant<T>(DependencyObject obj) where T : DependencyObject  
        {  
          if (obj is T)  
            return obj as T;  
      
          int childrenCount = VisualTreeHelper.GetChildrenCount(obj);  
          if (childrenCount < 1)  
            return null;  
      
          for (int i = 0; i < childrenCount; i++)  
          {  
            DependencyObject child = VisualTreeHelper.GetChild(obj, i);  
            if (child is T)  
              return child as T;  
          }  
          for (int i = 0; i < childrenCount; i++)  
          {  
            DependencyObject child = FindDescendant<T>(VisualTreeHelper.GetChild(obj, i));  
            if (child != null && child is T)  
              return child as T;  
          }  
          return null;  
        }  
      }  
      
      public enum SpecialFeatures  
      {  
        None,  
        Color,  
        Highlight  
      }  
      public class EditableStructures : INotifyPropertyChanged  
      {  
        public string StrName { get; set; }  
        public bool IsAccepted { get; set; }  
        public int NamInd { get; set; }  
        public bool IsGuessed { get;set;}  
        private SpecialFeatures _specialFeatures;  
        public SpecialFeatures SpecialFeatures  
        {  
          get { return _specialFeatures; }  
          set  
          {  
            _specialFeatures = value;  
            OnPropertyChanged("SpecialFeatures");  
          }  
        }  
        public event PropertyChangedEventHandler PropertyChanged;  
      
        protected void OnPropertyChanged(string name)  
        {  
          PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));  
        }  
      }  
    }  
    

    The result:
    194066-55.gif


    If the response is helpful, please click "Accept Answer" and upvote it.
    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.


1 additional answer

Sort by: Most helpful
  1. mauede 221 Reputation points
    2022-04-18T12:23:18.553+00:00

    Hi @Hui Liu-MSFT ,
    I have answered my concerns about your proposed solution.
    Thank you

    0 comments No comments

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.