2012-10-03 88 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

完美!謝謝澄清 –

相關問題