You can achieve this by using IMultiValueConverter , which will return true if Text is within the range, otherwise return false. Based on the value returned by converter, change background color .
Pass three parameters to the converter:
- The value of the actual text.
- Minimum value.
- The maximum value.
Converter
public class ItemExistInRangeConverter : IMultiValueConverter { public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) { bool itemsExistInRange = false; if (values.Length == 3) { int outputValue = int.MinValue; if (Int32.TryParse(values[0].ToString(), out outputValue)) { int minValue = (int)values[1]; int maxValue = (int)values[2]; itemsExistInRange = minValue <= outputValue && outputValue <= maxValue; } } return itemsExistInRange; } public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) { throw new NotImplementedException(); } }
Xaml
<DataGrid.Resources> <local:ItemExistInRangeConverter x:Key="ItemExistInRangeConverter"/> <sys:Int32 x:Key="MinimumValue">1</sys:Int32> <sys:Int32 x:Key="MaximumValue">50</sys:Int32> <Style x:Key="BackgroundColourStyle" TargetType="{x:Type TextBlock}"> <Style.Triggers> <DataTrigger Value="True"> <DataTrigger.Binding> <MultiBinding Converter="{StaticResource ItemExistInRangeConverter}"> <Binding Path="Text" RelativeSource="{RelativeSource Self}"/> <Binding Source="{StaticResource MinimumValue}"/> <Binding Source="{StaticResource MaximumValue}"/> </MultiBinding> </DataTrigger.Binding> <Setter Property="Background" Value="LightGreen" /> </DataTrigger> </Style.Triggers> </Style> </DataGrid.Resources>
Make sure the appropriate namespace is added at the root level:
xmlns:local="clr-namespace:NamespaceOfConverter" // Replace NamespaceOfConverter with namespace where converter resides. xmlns:sys="clr-namespace:System;assembly=mscorlib"
UPDATE (If you want to find an element in an array of numbers)
Assuming a property of your array of numbers exists in the code behind or viewing the model class.
First of all you need to set ItemsSource of DataGrid to DataTable instead of DataContext.
Secondly, set DataContext of DataGrid to this from code behind or an instance of viewModel class .
In addition, to update the GUI, your class must implement the INotifyPropertyChanged interface .
Now suppose you have a property:
public int[] RangeNumbers { get; set; }
By default, it will contain a list of numbers that you want to highlight.
XAML will look like this:
<DataGrid.Resources> <local:ItemExistInRangeConverter x:Key="ItemExistInRangeConverter"/> <Style x:Key="BackgroundColourStyle" TargetType="{x:Type TextBlock}"> <Style.Triggers> <DataTrigger Value="True"> <DataTrigger.Binding> <MultiBinding Converter="{StaticResource ItemExistInRangeConverter}"> <Binding Path="Text" RelativeSource="{RelativeSource Self}"/> <Binding Path="DataContext.RangeNumbers" RelativeSource="{RelativeSource FindAncestor, AncestorType=DataGrid}"/> </MultiBinding> </DataTrigger.Binding> <Setter Property="Background" Value="LightGreen" /> </DataTrigger> </Style.Triggers> </Style> </DataGrid.Resources>
Converter Code:
public class ItemExistInRangeConverter : IMultiValueConverter { public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) { bool itemsExistInRange = false; if (values.Length == 2) { int outputValue = int.MinValue; int[] rangeNumbers = (int[])values[1]; if (rangeNumbers != null && Int32.TryParse(values[0].ToString(), out outputValue)) { itemsExistInRange = rangeNumbers.Contains(outputValue); } } return itemsExistInRange; } public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) { throw new NotImplementedException(); } }
Elements will now be highlighted based on the starting numbers in RangeNumbers . But suppose that after that you update the array, you need to raise an event with a property change so that the GUI updates like this:
RangeNumbers = new int[] { 23, 45, 47, 69 }; OnPropertyChanged("RangeNumbers");