2012-10-03 99 views
4

我想知道,有没有什么方法可以设置自定义DataGrid选择颜色,当DataGrid或窗口,包含DataGrid,变得无效?如何设置自定义DataGrid无效选择颜色?

例如,这里是DataGridListBox,显示相同的数据。两个控件都有一个选定的项目。最初,DataGrid具有输入焦点:

enter image description here

一切正常 - 在ListBox选择的项目显示为灰色。那么,让我们将焦点移到ListBox

enter image description here

现在的DataGrid行为是不正确 - 选择颜色没有变化。我知道SystemColors.HighlightBrushKeySystemColors.ControlBrushKey。此XAML被放置在窗口的资源:

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

不过貌似DataGrid忽略了第二个 - SystemColors.ControlBrushKey,我想DataGrid的行为像任何其他控件(ListBoxComboBoxListView)。类似

东西我可以用触发器实现:

<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

但是这个解决方案是不完整的。首先,它选择了灰色,但未聚焦的单元格,即使是网格选择单元也是FullRow。第二件事 - 当应用程序窗口失去焦点时触发器不会触发。

有什么建议吗?

UPDATE

此错误在.NET 4.5中修复,所以它不再是实际的。

回答

2

我找到了解决方案,但看起来并不高雅。

基本问题是:

  • DataGrid.IsFocused永久false,因为焦点有 具体的细胞,而不是网格本身。
  • 没有办法确定单元格样式,网格中是否有任何关注的单元格 。您只能测试当前单元的IsFocused
  • 数据网格对关闭父窗口没有反应。

确定数据网格是否有焦点的唯一方法是检查DataGrid.CurrentCell属性。不幸的是,它是一个结构体,你不能触发器,它检查{x:Null}这个属性。

要解决这些问题,我需要两个附加属性。
其中的第一个意图是确定网格中是否有任何聚焦单元。其结果必然是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)); 

第二附加属性必须改变,当网格的父窗口变成inactve:

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> 

是否有更好的解决方案?

2

我以DataGrid.Resources在.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}"/> 

+0

在'DataGrid'此bug已被固定在4.5 achived这种行为。现在'DataGrid'的行为与任何“普通”'Selector'类似。 – Dennis

+0

完美!谢谢澄清 –

相关问题