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;
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:
<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:
<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:
<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?