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 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:
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:
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:
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:
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.