Я использую Adorner для размещения треугольника индикатора в выбранных ячейках WPF DataGrid (тот же эффект, который вы получаете при вставке комментария в ячейку в Excel). К сожалению, я получаю случайные рекламные ролики, где они не должны.WPF DataGrid и Adorners
Предположим, что есть 3 ячейки, у которых должен быть Adorner; Я получаю 3 дополнительных ячейки, которые также имеют Adorner. Я доказал, что только 3 создаются в коде, хотя их 6. Я создаю/удаляю Adorners в событии ElementGenerated.
Дополнительные экземпляры всегда находятся на ячейках, которые еще не находятся в визуальной области сетки, и поэтому я уверен, что проблема связана с виртуализацией столбцов сетки и что сетка повторно использует ячейки, а не создавая новые, и как таковое событие ElementGenerated не запускается снова, и Adorner не удаляется там, где он не нужен.
Я не могу найти событие, которое я мог бы использовать, когда ячейка повторно используется. Любые предложения были бы с благодарностью получены.
Это код треугольника Adorner: -
public class TriangleAdorner : Adorner
{
private readonly double _offsetX;
private readonly double _offsetY;
public TriangleAdorner(UIElement adornedElement)
: this(adornedElement, 0, 0)
{
}
public TriangleAdorner(UIElement adornedElement, double offsetX, double offsetY)
: base(adornedElement)
{
_offsetX = offsetX;
_offsetY = offsetY;
}
protected override void OnRender(DrawingContext drawingContext)
{
//Rect adornedElementRect = new Rect(this.AdornedElement.DesiredSize);
// all examples seem to use the above but this didn't get the adorner in the correct place for me
Rect adornedElementRect = new Rect(this.AdornedElement.RenderSize);
PointCollection myPointCollection = new PointCollection
{
new Point(adornedElementRect.TopLeft.X + 6 + _offsetX, adornedElementRect.TopLeft.Y + 1 + _offsetY),
new Point(adornedElementRect.TopLeft.X + 1 + _offsetX, adornedElementRect.TopLeft.Y + 1 + _offsetY),
new Point(adornedElementRect.TopLeft.X + 1 + _offsetX, adornedElementRect.TopLeft.Y + 6 + _offsetY)
};
StreamGeometry streamGeometry = new StreamGeometry();
using (StreamGeometryContext geometryContext = streamGeometry.Open())
{
geometryContext.BeginFigure(myPointCollection[0], true, true);
PointCollection points = new PointCollection
{
myPointCollection[1],
myPointCollection[2]
};
geometryContext.PolyLineTo(points, true, true);
}
drawingContext.DrawGeometry(Brushes.Red, new Pen(Brushes.Red, 0), streamGeometry);
}
protected override Size MeasureOverride(Size constraint)
{
var result = base.MeasureOverride(constraint);
InvalidateVisual();
return result;
}
И событие, которое добавляет/удаляет: -
private void DataGrid_ElementGenerated(object sender, ElementGeneratedEventArgs e)
{
FrameworkElement element = (FrameworkElement) e.DataGridCell;
if (element == null) return;
AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(element);
if (adornerLayer != null)
{
if (CellAdornerRequired())
{
Adorner[] children = adornerLayer.GetAdorners(element);
if (children == null || !children.Any())
{
adornerLayer.Add(new TriangleAdorner(element));
}
}
else
{
Adorner[] children = adornerLayer.GetAdorners(element);
if (children != null && children.Any())
{
foreach (var adorner in children)
{
adornerLayer.Remove(adorner);
}
}
}
}
}
Дополнительные символы отображаются в столбцах, находящихся за пределами области просмотра. DataGrid не загружает ячейки в этих столбцах, пока они не потребуются. Я не упомянул, что Grid - это настроенная версия WPF DataGrid и что есть специальный столбец шаблона. Я создал Guid внутри класса TriangleAdorner, чтобы я мог идентифицировать adorner в событии OnRender. Кажется, что один и тот же экземпляр adorner отображается в нескольких местах. Спасибо за ваш ответ. – EzaBlade