我找到了解決方案,但看起來並不高雅。
基本問題是:
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>
是否有更好的解決方案?
在'DataGrid'此bug已被固定在4.5 achived這種行爲。現在'DataGrid'的行爲與任何「普通」'Selector'類似。 – Dennis
完美!謝謝澄清 –