解決策を見つけましたが、エレガントに見えません。
基本的な問題は次のとおりです。
DataGrid.IsFocused
false
フォーカスにはグリッド自体ではなく具体的なセルがあるため、永続的です。
- セル スタイルで判断する方法はありません。グリッドにフォーカスされたセルはありますか。
IsFocused
現在のセルのみをテストできます。
- データ グリッドは、親ウィンドウの非アクティブ化に反応しません。
データ グリッドにフォーカスがあるかどうかを判断する唯一の方法は、DataGrid.CurrentCell
プロパティを確認することです。残念ながら、これは構造体であり、このプロパティをチェックするトリガーを作成することはできません{x:Null}
。
これらの問題を解決するには、2 つの添付プロパティが必要です。
それらの最初の目的は、グリッドにフォーカスされたセルがあるかどうかを判断することです。結果はbool
、ソースはDataGridCellInfo
である必要があるため、まず、コンバーターを記述する必要があります。
[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's no focused cell.
return ((DataGridCellInfo)value).IsValid;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return DependencyProperty.UnsetValue;
}
}
添付プロパティ:
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));
グリッドの親ウィンドウが非アクティブになると、2 番目の添付プロパティを変更する必要があります。
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));
それでは、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}}}"/>
次に、適切な背景色を設定するためのセル スタイルが必要です。
<!-- A style of selected cell in DataGrid, when there's 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>
添付プロパティの値が変更されたときにトリガーを起動するグリッド スタイル:
<!--
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>
より良い解決策はありますか?