У нас есть стандартный шаблон Validation.ErrorTemplate, который рисует красную рамку и отображает значок ошибки в верхнем правом углу элементов управления с ошибками проверки. Это прекрасно работает везде, кроме верхнего ряда сетки данных, где изображение обрезается с помощью (я думаю) ScrollViewer сетки.
В идеале верхний значок ошибки должен отображаться полностью, а нижний не должен отображаться до тех пор, пока эта строка не станет видимой.
Вот пример, который воспроизводит проблему в настолько малом количестве кода, насколько я могу управлять:
<Window x:Class="WpfClippedAdorner.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:draw="clr-namespace:System.Drawing;assembly=System.Drawing"
xmlns:valueConverters="clr-namespace:WpfClippedAdorner.ValueConverters"
mc:Ignorable="d"
Title="MainWindow" Height="150" Width="200">
<Grid>
<Grid.Resources>
<valueConverters:IconToImageSourceConverter x:Key="IconToImageSourceConverter" />
</Grid.Resources>
<DataGrid AutoGenerateColumns="False" Height="75" Width="150"
ClipToBounds="False">
<DataGrid.Columns>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<DockPanel LastChildFill="true">
<Border BorderBrush="red" BorderThickness="1" >
<TextBlock Text="{Binding Text}" />
</Border>
<Image Source="{Binding Source={x:Static draw:SystemIcons.Error}, Converter={StaticResource IconToImageSourceConverter}, Mode=OneWay}"
Margin="-10,-8,0,0" Height="16" Width="16" VerticalAlignment="Top"/>
</DockPanel>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
<DataGrid.Items>
<TextBlock Text="Test1"/>
<TextBlock Text="Test2"/>
<TextBlock Text="Test3"/>
<TextBlock Text="Test4"/>
</DataGrid.Items>
</DataGrid>
</Grid>
</Window>
Обратите внимание, что ClipToBounds имеет значение False, но не решает проблему.
Я также попытался извлечь шаблон элемента управления DataGrid и установить везде ClipToBounds = "False" без видимого эффекта.
Вот конвертер значений, который я использовал для отображения значка на тот случай, если вы захотите воссоздать мой тестовый проект.
namespace WpfClippedAdorner.ValueConverters
{
using System;
using System.Diagnostics;
using System.Drawing;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Media.Imaging;
/// <summary>
/// Converts a windows icon to an image source that can be used in WPF
/// </summary>
/// <seealso cref="System.Windows.Data.IValueConverter" />
public class IconToImageSourceConverter : IValueConverter
{
/// <inheritdoc />
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var icon = value as Icon;
if (icon == null)
{
Trace.TraceWarning("Attempted to convert {0} instead of Icon object in IconToImageSourceConverter", value);
return null;
}
ImageSource imageSource = Imaging.CreateBitmapSourceFromHIcon(
icon.Handle,
Int32Rect.Empty,
BitmapSizeOptions.FromWidthAndHeight(16, 16));
return imageSource;
}
/// <inheritdoc />
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
Наконец, вот фактический стиль, который мы используем для выделения ошибок валидации, на случай, если я допустил ошибки в его упрощении.
<Style x:Key="ErrorDisplay" TargetType="FrameworkElement">
<Setter Property="Margin" Value="5,5,5,5" />
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<DockPanel LastChildFill="true">
<AdornedElementPlaceholder Name="customAdorner" VerticalAlignment="Center" >
<Border BorderBrush="red" BorderThickness="1" />
</AdornedElementPlaceholder>
<Image Source="{Binding Source={x:Static draw:SystemIcons.Error}, Converter={StaticResource IconToImageSourceConverter}, Mode=OneWay}"
Margin="-10,-8,0,0" Height="16" Width="16" VerticalAlignment="Top"
ToolTip="{Binding ElementName=customAdorner, Path=AdornedElement.(Validation.Errors).CurrentItem.ErrorContent}"/>
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors).CurrentItem.ErrorContent}" />
</Trigger>
</Style.Triggers>
</Style>