How to draw the user's attention only to some items of a ListBox

mauede

Well-known member
Joined
Sep 1, 2021
Messages
103
Location
Northwood - UK
Programming Experience
Beginner
I wonder whether it is possible to highlight or change the color of the text or place a symbol (for example "!") or something else to attract the user's attention only on some items of the rightmost ListBox in the attached GUI.
The reason is to reduce the user's time devote to double-checking the goodness of automatically renamed clinical structures.
Thank you.

GUI.PNG
 
Since you mentioned in another thread that you don't have any disability compliance requirements, you can make use of colors. Recall the previous link I sent about UI color design. only choose 2-3 colors for use on your UI. Choose the 3rd color as your designated error color. If you want to stick with your color scheme, pick an outlandish color like Barney-the-dinosaur purple as the background color for your error items. Also change the border color of the last list box so that the user would know to look there for something being wrong.
 
Since you mentioned in another thread that you don't have any disability compliance requirements, you can make use of colors. Recall the previous link I sent about UI color design. only choose 2-3 colors for use on your UI. Choose the 3rd color as your designated error color. If you want to stick with your color scheme, pick an outlandish color like Barney-the-dinosaur purple as the background color for your error items. Also change the border color of the last list box so that the user would know to look there for something being wrong.
OK. However, the difficulty I face is changing the background colour only of the ListBox items that show guessed structure names through the Dice coefficient. You know how the editable ListBox is populated as I mimicked your instrumental example. The code knows the indexes of the ListBox elements that host guessed names but which ones and how many are only known at runtime. That is the essence of my question that I could not convey well enough.
 
Not only can you bind the values to be displayed, you can also bind the color attributes of various WPF UI elements.

 
Not only can you bind the values to be displayed, you can also bind the color attributes of various WPF UI elements.

Thank you. I was thinking of that while I was in the shower. I was about to ask you if this would be possible.
I will read the documentation you sent.
I believe I will be able to change the background colour of some items from the code behind at runtime.
 
If you do things the right way, this will be the time you'll end up needing the INotifyPropertyChanged implementation because when the text gets changed to something invalid, you'll want to update the background color in your view model. The view model has to tell the view to pick up the new background color.

If you continue to write code behind ala WinForms, then you'll have to figure out which UI element you need to update.
 
If you do things the right way, this will be the time you'll end up needing the INotifyPropertyChanged implementation because when the text gets changed to something invalid, you'll want to update the background color in your view model. The view model has to tell the view to pick up the new background color.

If you continue to write code behind ala WinForms, then you'll have to figure out which UI element you need to update.
The first obstacle is how to identify the ListBox items whose background color has to be changed.
Each ListBox item is a TextBlock. I can bind the Background property of the TextBlock to a brush color defined in the code-behind. However, only a few ListBox items (TextBlocks) have to display a different backgroung color. Not all of them.
The XAML definition of the ListBox is as follows:


ListBox:
    <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}" Background="{Binding TheBackground}"  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}"  Grid.Column="2" HorizontalAlignment="Stretch"/>
                    </Grid>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>


The code that prepares the strings to be displayed in the ListBox consists of three sections.
Section_1 The strings (structure names) from a patient that exactly match a protocol defined string are copied to the List<string> RenamedStructNames as follows:

Section-1:
  RenamedStructNames.Clear();
            for (int k = 0; k < strucNames.Count; k++)
            {
                if (protNames.Contains(strucNames[k]))
                {
                    RenamedStructNames.Add(strucNames[k]);
                }
                else
                    RenamedStructNames.Add(" ");
            }

Section_2 Patient structures that pertain to the tumor have standard root names followed by numbers that indicate the radiation dose levels. So the match between the patient structures and the protocol-defined tumor structures can only be made on the root names allowing for different radiation dose levels. Examples:
"GTV_3000", "PTV_7000", "CTV_6000", "ITV_5500", "IGTV_8400"
Patient structure names (strings) whose root matches a protocol-defined root name are
are copied to the List<string> RenamedStructNames as follows:


C#:
 double diceCoef = 0;
            for (int k = 0; (k < strucNamesLength); k++)
            {
                if (!protNames.Contains(strucNames[k]))
                {
                    if(Regex.IsMatch(strucNames[k], @"(G|P|I|C)TV\d+_\d+")
                     | Regex.IsMatch(strucNames[k], @"(I)CTV\d+_\d+")
                     | Regex.IsMatch(strucNames[k], @"(I)GTV\d+_\d+"))
                    {
                        int index = strucNames[k].IndexOf("_");
                        string substr = strucNames[k].Substring(index + 1);
                        if(substr.Length > 0)
                        {
                            if (substr.All(char.IsDigit))
                            {
                                RenamedStructNames[k] = strucNames[k];
                            }
                        }
                    }
                    
                    else if (strucNames[k].IndexOf('_') >= 0 & strucNames[k].IndexOf('_') > strucNames[k].Length -1)
                    {
                        string substr = strucNames[k].Substring(strucNames[k].IndexOf('_') + 1);
                        if (substr.All(char.IsDigit))
                        {
                            RenamedStructNames[k] = strucNames[k];
                        }
                    }

Section-3 The remaining patient structure names for which the Dice Coefficient algorithm is invoked to guess a name that is the most similar to the protocol-defined structure names. These are the structure names (strings) that have to be reviewed by the user. The ListBox items (TextBlocks) hosting these names have to display a background color different from the other items.
The code that produces these names is as follows:


C#:
     else
                    {
                        string DiceGuess = "";
                        diceCoef = DiceCoeff(strucNames[k], protNames, ref DiceGuess);
                        if (RenamedStructNames.Contains(DiceGuess) | (diceCoef < DiceThreshold))    // IF STRING ADDED THEN ADD A WHITE STRING
                        {
                            RenamedStructNames[k] = " ";
                        }
                        else
                        {
                            RenamedStructNames[k] = DiceGuess;
                        }
                    }


The ListBox is populated with the content of the List<string> RenamedStructNames upon clicking a button as follows:


C#:
            foreach (string str in EditedList)
            {
                AutoNames.Add(new EditableStructures { StrName = str,  IsAccepted = false, NamInd = j});
                j++;
            }
            int NumGuessed = 0;
            int NumOriginal = 0;
            var Guessed = AutoNames.Where(m => !string.IsNullOrWhiteSpace(m.StrName)).ToList();
            NumGuessed = Guessed.Count;
            NumOriginal = strucNames.Count;
            MessageBox.Show($" {NumGuessed} structures automatically renamed out of {NumOriginal} patient structures\n", "Is this patient belonging to this trial? ", MessageBoxButton.OK, MessageBoxImage.Information);
            UpdateAutoStrucNames();


  public void UpdateAutoStrucNames()
        {
            EditableStructs.ItemsSource = (System.Collections.IEnumerable)AutoNames;
        }


So the event that populates the ListBox is a Button-click.
The code knows the indexes of the "guessed" names.
I should change the background color of the ListBox items that host the "guessed" structure names as part of this event.
The code knows the indexes of the List<string> that correspond to the "guessed" names.
My question is:
How can I change the background color of the ListBox items hosting the names generated in Section-3?

Thank you in advance for your help.
 
If you do things the right way, this will be the time you'll end up needing the INotifyPropertyChanged implementation because when the text gets changed to something invalid, you'll want to update the background color in your view model. The view model has to tell the view to pick up the new background color.

If you continue to write code behind ala WinForms, then you'll have to figure out which UI element you need to update.
The indexes of the ListBox items, whose background colour has to be changed, are known at runtime.
Since the length of the ListBox is also established at runtime I think I cannot use indexes to reach the single ListBox items before it is dynamically generated.
The colour-changing process will follow the ListBox creation. That is why I have to implement InotifyPropertyChange.
In terms of changing the Background property for a subset of the ListBox items, may I use indexes the same way as if the ListBox was a vector of strings?

Let's assume the ListBox has 10 items and I need to change the background colour of the 3rd and the 5th item. How can I do that?
Thank you
 
Back
Top Bottom