The following DataTemplate.DataTrigger
makes the age display red if it is equal to 30.
How do I make the age display red if it is greater than 30?
<DataTemplate DataType="{x:Type local:Customer}">
<Grid x:Name="MainGrid" Style="{StaticResource customerGridMainStyle}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="150"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock Grid.Column="0" Grid.Row="0" Text="First Name" Margin="5"/>
<TextBlock Grid.Column="1" Grid.Row="0" Text="{Binding FirstName}" Margin="5"/>
<TextBlock Grid.Column="0" Grid.Row="1" Text="Last Name" Margin="5"/>
<TextBlock Grid.Column="1" Grid.Row="1" Text="{Binding LastName}" Margin="5"/>
<TextBlock Grid.Column="0" Grid.Row="2" Text="Age" Margin="5"/>
<TextBlock x:Name="Age" Grid.Column="1" Grid.Row="2" Text="{Binding Age}" Margin="5"/>
</Grid>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Path=Age}">
<DataTrigger.Value>30</DataTrigger.Value>
<Setter TargetName="Age" Property="Foreground" Value="Red"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
You could create an IValueConverter
, which converts an integer to a boolean based on the CutOff
. Then use DataTrigger.Value
of True
(or False
, depending on what you are returning).
WPF DataTrigger
s are strictly equality comparers if I remember correctly.
So something similar to:
public class CutoffConverter : IValueConverter {
object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
return ((int)value) > Cutoff;
}
object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
throw new NotImplementedException();
}
public int Cutoff { get; set; }
}
Then use the following XAML.
<Window.Resources>
<myNamespace:CutoffConverter x:Key="AgeConverter" Cutoff="30" />
</Window.Resources>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Path=Age,
Converter={StaticResource AgeConverter}}">
<DataTrigger.Value>true</DataTrigger.Value>
<Setter TargetName="Age" Property="Foreground" Value="Red"/>
</DataTrigger>
</DataTemplate.Triggers>
I'd recommend using an IValueConverter
to bind to the Foreground
element of the Age TextBlock
and isolating the coloring logic there.
<TextBlock x:Name="Age" Grid.Column="1" Grid.Row="2" Text="{Binding Age}" Foreground="{Binding Path=Age, Converter={StaticResource AgeToColorConverter}}" Margin="5"/>
Then in the Code:
[ValueConversion(typeof(int), typeof(Brush))]
public class AgeToColorConverter : IValueConverter
{
public object Convert(object value, Type target)
{
int age;
Int32.TryParse(value.ToString(), age);
return (age >= 30 ? Brushes.Red : Brushes.Black);
}
}
I believe there is a simpler way of acheiving the goal by using the powers of MVVM and INotifyPropertyChanged
.
With the Age
property create another property which will be a boolean called IsAgeValid
. The IsAgeValid
will simply be an on demand check which does not technically need an the OnNotify
call. How?
To get changes pushed to the Xaml, place the OnNotifyPropertyChanged
for IsAgeValid
within the Age
setter instead.
Any binding to IsAgeValid
will have a notify message sent on any Age
change which is really what is being looked at.
Once setup, of course bind the style trigger for false and true accordingly to the IsAgeValid
result.
public bool IsAgeValid{ get { return Age > 30; } }
public int Age
{
get { return _Age; }
set
{
_Age=value;
OnPropertyChanged("Age");
OnPropertyChanged("IsAgeValid"); // When age changes, so does the
// question *is age valid* changes. So
// update the controls dependent on it.
}
}