Reputation: 3050
I want to change the foreground color of cells that hold negative numbers, but I don't know how to specify the DataTrigger that would let me. I'm using something like this:
<Style x:Key="NumberCellStyle" BasedOn="{StaticResource CellStyle}">
<Style.Triggers>
<DataTrigger Binding="{Binding Converter={StaticResourceExtension SignConverter}}" Value="-1">
<Setter Property="TextBlock.Foreground" Value="Red"/>
</DataTrigger>
</Style.Triggers>
</Style>
But in the SignConverter converter I get the whole ViewModel instead of the numeric value I want to convert. I want this to work across the app, without me needing to specify the correct Path for each binding.
Thank you very much!
Upvotes: 2
Views: 2622
Reputation:
How would you get this code to read the IsSelected property of the DataGrid itself? I've tried the following code but can't work out how to get the bool value into the ConverterParameter, where the DecimalBrushConverter reads the parameter and provides the SelectedBrush if isSelected==true.
public class DataGridDecimalColumn : DataGridTextColumn { private readonly DecimalBrushConverter _brushConverter = new DecimalBrushConverter { NegativeBrush = Brushes.Red, PositiveBrush = Brushes.Black, ZeroBrush = Brushes.Black, SelectedBrush = Brushes.White };
private Binding _foregroundBinding;
private DecimalBrushConverter BrushConverter
{
get { return _brushConverter; }
}
protected override FrameworkElement GenerateElement(DataGridCell cell, object dataItem)
{
var element = base.GenerateElement(cell, dataItem) as TextBlock;
if (element != null)
element.SetBinding(TextBlock.ForegroundProperty, GetForegroundBinding());
return element;
}
private Binding GetForegroundBinding()
{
if (_foregroundBinding == null)
{
var binding = (Binding) Binding;
var bindingToRow = new Binding
{
Path = new PropertyPath("IsSelected"),
RelativeSource=new RelativeSource(RelativeSourceMode.FindAncestor,typeof(DataGridRow),1)
};
_foregroundBinding = new Binding
{
Path = binding.Path,
Converter = BrushConverter,
ConverterParameter = bindingToRow
};
}
return _foregroundBinding;
}
}
Upvotes: 0
Reputation: 3050
Better way, write a custom column.
The code follows for anyone that's in the same situation:
public class DataGridDecimalColumn : DataGridTextColumn
{
Binding foregroundBinding;
DecimalBrushConverter brushConverter = new DecimalBrushConverter {
NegativeBrush = Brushes.Red,
PositiveBrush = Brushes.Black,
ZeroBrush = Brushes.Black,
};
protected override FrameworkElement
GenerateElement(DataGridCell cell, object dataItem)
{
var element = base.GenerateElement(cell, dataItem) as TextBlock;
element.SetBinding(TextBlock.ForegroundProperty, GetForegroundBinding());
return element;
}
Binding
GetForegroundBinding()
{
if(foregroundBinding == null) {
var binding = (Binding)Binding;
foregroundBinding = new Binding {
Path = binding.Path,
Converter = BrushConverter,
};
}
return foregroundBinding;
}
public DecimalBrushConverter
BrushConverter
{
get { return brushConverter; }
set { brushConverter = value; }
}
}
DecimalBrushConverter simple takes a decimal? and converts it to one of the specified brushes depending on its value.
Upvotes: 2
Reputation: 3050
OK, I didn't find a way to solve my original problem, but I'll work around it by using a DataGridTemplateColumn with templates that correctly set the Foreground color depending on the value that's bind to them.
Upvotes: 0
Reputation: 30418
What control are you applying the style too? It sounds like whatever you are applying it to doesn't have any specific bindings set for itself, so it is just inheriting its parents' value, which ends up being your ViewModel
instance.
Update: Based on the comment, I think that you need to specify a Path in the Binding expression of the style. Since no path is specified, it just uses the current DataContext
, which ends up being the entire ViewModel
instance.
Upvotes: 0