How to set custom color for inactive color DataGrid?

I am wondering if there is a way to set a custom DataGrid selection color when a DataGrid or a window containing a DataGrid becomes inactive?

For example, here are DataGrid and ListBox displaying the same data. Both controls have one selected item. Initially, the DataGrid has input focus:

enter image description here

Everything looks fine - the selected item in the ListBox is ListBox . Then move the focus to the ListBox :

enter image description here

Now the behavior of the DataGrid is wrong - the color of the selection has not changed.
I know about SystemColors.HighlightBrushKey and SystemColors.ControlBrushKey . This XAML has been placed in window resources:

  <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="BlueViolet"/> <SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="DarkGray"/> 

But it looks like the DataGrid ignoring the second - SystemColors.ControlBrushKey , and I want the DataGrid to behave like any other controls ( ListBox , ComboBox , ListView ).

Something like this I can achieve with triggers:

 <Style TargetType="{x:Type DataGridCell}"> <Style.Triggers> <MultiTrigger> <MultiTrigger.Conditions> <Condition Property="IsFocused" Value="False"/> <Condition Property="IsSelected" Value="True"/> </MultiTrigger.Conditions> <Setter Property="Background" Value="DarkGray"/> </MultiTrigger> </Style.Triggers> </Style> 

enter image description here

But this solution is incomplete. First of all, it is selected in gray, but the unfocused cell, even the grid selection cell, is FullRow . The second thing - the trigger does not work when the application window loses focus.

Any suggestions?

UPDATE

This bug was fixed in .NET 4.5, so it is no longer relevant.

+4
source share
2 answers

I found a solution, but it does not look elegant.

Main problems:

  • DataGrid.IsFocused constantly false , because the concrete cell, not the grid itself.
  • It is not possible to determine the cell style whether there is a focused cell in the grid. You can only check IsFocused for the current cell.
  • The data grid does not respond to the deactivation of the parent window.

The only way to determine if the data grid has focus is to check the DataGrid.CurrentCell property. Unfortunately, this is a structure, and you cannot make a trigger that checks this property for {x:Null} .

To solve these problems, I need two attached properties.
The first one is designed to determine if there is a focused cell in the grid. The result should be bool , the source of DataGridCellInfo , therefore, first of all, the converter should be written:

 [ValueConversion(typeof(DataGridCellInfo), typeof(bool))] public sealed class DataGridCellInfoToBooleanConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { if (value == null || value.GetType() != typeof(DataGridCellInfo) || targetType != typeof(bool)) return DependencyProperty.UnsetValue; // IsValid will be false, if there no focused cell. return ((DataGridCellInfo)value).IsValid; } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { return DependencyProperty.UnsetValue; } } 

Nested Property:

  public static bool GetHasFocusedCell(DependencyObject obj) { return (bool)obj.GetValue(HasFocusedCellProperty); } public static void SetHasFocusedCell(DependencyObject obj, bool value) { obj.SetValue(HasFocusedCellProperty, value); } public static readonly DependencyProperty HasFocusedCellProperty = DependencyProperty.RegisterAttached( "HasFocusedCell", typeof(bool), typeof(FocusedCellBehavior), new UIPropertyMetadata(false)); 

The second attached property should be changed when the parent window of the grid becomes inactive:

  public static bool GetIsParentWindowActive(DependencyObject obj) { return (bool)obj.GetValue(IsParentWindowActiveProperty); } public static void SetIsParentWindowActive(DependencyObject obj, bool value) { obj.SetValue(IsParentWindowActiveProperty, value); } public static readonly DependencyProperty IsParentWindowActiveProperty = DependencyProperty.RegisterAttached( "IsParentWindowActive", typeof(bool), typeof(FocusedCellBehavior), new UIPropertyMetadata(false)); 

Now bind the attached properties in XAML:

  <!-- A converter to define, is there any focused cell in DataGrid --> <local:DataGridCellInfoToBooleanConverter x:Key="DataGridCellInfoToBooleanConverter"/> <DataGrid Grid.Row="0" SelectionUnit="FullRow" SelectionMode="Single" ItemsSource="{Binding}" local:FocusedCellBehavior.HasFocusedCell="{Binding CurrentCell, RelativeSource={RelativeSource Mode=Self}, Converter={StaticResource DataGridCellInfoToBooleanConverter}}" local:FocusedCellBehavior.IsParentWindowActive="{Binding IsActive, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}"/> 

Next, I need a cell style to set the appropriate background color:

  <!-- A style of selected cell in DataGrid, when there no any focused cells in DataGrid --> <Style TargetType="{x:Type DataGridCell}" x:Key="InactiveSelectedCellStyle"> <Style.Triggers> <Trigger Property="IsSelected" Value="True"> <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/> </Trigger> </Style.Triggers> </Style> 

and a grid style for triggering triggers when attached properties change their values:

  <!-- A style of DataGrid, that defines a couple of triggers, which being fired when helper attached properties will change their values --> <Style TargetType="{x:Type DataGrid}"> <Style.Triggers> <Trigger Property="local:FocusedCellBehavior.IsParentWindowActive" Value="False"> <Setter Property="CellStyle" Value="{StaticResource InactiveSelectedCellStyle}"/> </Trigger> <Trigger Property="local:FocusedCellBehavior.HasFocusedCell" Value="False"> <Setter Property="CellStyle" Value="{StaticResource InactiveSelectedCellStyle}"/> </Trigger> </Style.Triggers> </Style> 

Are there any better solutions?

+2
source

I achieved this behavior using DataGrid.Resources in .Net 4.5

 <DataGrid.Resources> <SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightBrushKey}" Color="{x:Static SystemColors.HighlightColor}"/> <SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightTextBrushKey}" Color="{x:Static SystemColors.HighlightTextColor}"/> 

+2
source

Source: https://habr.com/ru/post/1437517/


All Articles