#wpf
#wpf
Вопрос:
Я пытаюсь отобразить границу DataGridRow поверх границы DataGrid. Возможно ли это вообще с помощью стиля или я должен использовать пользовательский элемент оформления?
Я хочу добиться чего-то подобного:
Я пытался использовать Panel.ZIndex
и ClipToBounds="False"
, но, похоже, в этом случае это не работает.
<Style x:Key="MyDataGridRowStyle" TargetType="{x:Type DataGridRow}">
<Setter Property="SnapsToDevicePixels" Value="true" />
<Setter Property="Validation.ErrorTemplate" Value="{x:Null}" />
<Setter Property="ValidationErrorTemplate">
<Setter.Value>
<ControlTemplate>
<TextBlock
Margin="2,0,0,0"
VerticalAlignment="Center"
Foreground="Red"
Text="!" />
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridRow}">
<Border
x:Name="DGR_Border"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
ClipToBounds="False"
SnapsToDevicePixels="True">
<SelectiveScrollingGrid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<DataGridCellsPresenter
Grid.Column="1"
ItemsPanel="{TemplateBinding ItemsPanel}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
<DataGridDetailsPresenter
Grid.Row="1"
Grid.Column="1"
SelectiveScrollingGrid.SelectiveScrollingOrientation="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}, Path=AreRowDetailsFrozen, Converter={x:Static DataGrid.RowDetailsScrollingConverter}, ConverterParameter={x:Static SelectiveScrollingOrientation.Vertical}}"
Visibility="{TemplateBinding DetailsVisibility}" />
<DataGridRowHeader
Grid.RowSpan="2"
SelectiveScrollingGrid.SelectiveScrollingOrientation="Vertical"
Visibility="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}, Path=HeadersVisibility, Converter={x:Static DataGrid.HeadersVisibilityConverter}, ConverterParameter={x:Static DataGridHeadersVisibility.Row}}" />
</SelectiveScrollingGrid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsNewItem" Value="True">
<Setter Property="Margin" Value="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}, Path=NewItemMargin}" />
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter Property="BorderThickness" Value="1" />
<Setter Property="BorderBrush" Value="Red" />
<Setter Property="Margin" Value="-1,-1,-1,-1" />
<Setter Property="Panel.ZIndex" Value="123" />
</Trigger>
</Style.Triggers>
</Style>
Ответ №1:
Из-за жесткости WPF это невозможно использовать Panel.ZIndex
таким образом, поскольку его можно использовать только на том же уровне. Несколько решений этой проблемы:
-
Пользовательский редактор, который рисует прямоугольник выделения для выбранных строк (должен использовать слой adorner выше / на том же уровне границы DataGrid) пользовательский шаблон можно использовать для добавления
AdornerDecorator
чуть выше границы. -
Добавьте
Canvas
и<Rectangle x:Name="PART_SelectionRectangle" />
в шаблон DataGrid, подкласс DataGrid и измените положение прямоугольника в Canvas на основе текущего выделения в вашей подклассовой DataGrid.
Я не уверен, есть ли какой-либо способ сделать это только с помощью style без подкласса DataGrid / добавления к нему обработчиков событий, возможно, с помощью пользовательского конвертера, который вычисляет положение и размер прямоугольника выделения и свойства привязки Rectangle
с использованием этого конвертера.