Den*_*nis 5 c# wpf wpfdatagrid
我想知道,有什么方法可以设置自定义DataGrid选择颜色,何时DataGrid或包含 的窗口DataGrid变为非活动状态?
例如,这里是DataGridand ListBox,显示相同的数据。两个控件都有一个选定的项目。最初,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"/>
Run Code Online (Sandbox Code Playgroud)
但看起来DataGrid忽略了第二个 - SystemColors.ControlBrushKey,我想DataGrid表现得像任何其他控件(ListBox, ComboBox, ListView)。
我可以用触发器实现类似的东西:
<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>
Run Code Online (Sandbox Code Playgroud)

但是这个解决方案是不完整的。首先,它使选中但未聚焦的单元格变灰,甚至网格选择单元是FullRow。第二件事 - 当应用程序窗口失去焦点时触发器不会触发。
有什么建议?
更新。
此错误已在 .NET 4.5 中修复,因此不再实际。
我已经找到了解决方案,但它看起来并不优雅。
基本问题是:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
附属财产:
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));
Run Code Online (Sandbox Code Playgroud)
当网格的父窗口变为非活动状态时,必须更改第二个附加属性:
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));
Run Code Online (Sandbox Code Playgroud)
现在,让我们在 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}}}"/>
Run Code Online (Sandbox Code Playgroud)
接下来,我需要一个单元格样式来设置适当的背景颜色:
<!-- 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>
Run Code Online (Sandbox Code Playgroud)
以及当附加属性将更改其值时触发触发器的网格样式:
<!--
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>
Run Code Online (Sandbox Code Playgroud)
还有更好的解决方案吗?
| 归档时间: |
|
| 查看次数: |
5081 次 |
| 最近记录: |