5

カスタムDataGrid選択色を設定する方法はありますか?DataGridを含むウィンドウDataGridが非アクティブになるときは?

たとえば、これはDataGridListBoxで、同じデータを表示しています。どちらのコントロールにも、1 つの項目が選択されています。最初は、DataGrid入力フォーカスがあります:

ここに画像の説明を入力

すべて問題ないように見えます - で選択されたアイテムListBoxはグレー表示されます。次に、フォーカスをに移動しましょうListBox:

ここに画像の説明を入力

の動作DataGridが正しくなくなりました - 選択色は変更されていません。
と について知っていSystemColors.HighlightBrushKeyますSystemColors.ControlBrushKey。この XAML は、ウィンドウのリソースに配置されました。

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

DataGridしかし、2番目のものを無視するように見えます- SystemColors.ControlBrushKey、そして私は他DataGridのコントロール(、、)のように振る舞いListBoxたいです。 ComboBoxListView

トリガーで達成できる同様のこと:

<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>

ここに画像の説明を入力

しかし、この解決策は不完全です。まず、選択されたセルがグレー表示されますが、フォーカスされていないセル、さらにはグリッドの選択単位ですFullRow。2 つ目は、アプリケーション ウィンドウがフォーカスを失ったときにトリガーが起動しないことです。

助言がありますか?

更新します。

このバグは .NET 4.5 で修正されたため、もはや実際のものではありません。

4

2 に答える 2

2

解決策を見つけましたが、エレガントに見えません。

基本的な問題は次のとおりです。

  • DataGrid.IsFocusedfalseフォーカスにはグリッド自体ではなく具体的​​なセルがあるため、永続的です。
  • セル スタイルで判断する方法はありません。グリッドにフォーカスされたセルはありますか。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>

より良い解決策はありますか?

于 2012-10-03T09:53:12.627 に答える