2

Adorner を使用して、WPF DataGrid の選択したセルにインジケーターの三角形を配置しています (Excel のセルにコメントを挿入するときと同じ効果)。残念ながら、ランダムなアドナーが表示されるべきではない場所に表示されています。

Adorner を持つセルが 3 つあるとします。Adorner もある 3 つの余分なセルを取得しています。6 つ表示されているにもかかわらず、コードで作成されているのは 3 つだけであることを証明しました。ElementGenerated イベントで Adorners を作成/削除します。

余分なインスタンスは常に、グリッドの視覚領域にまだないセル上にあるため、問題はグリッド列の仮想化が原因であり、グリッドが新しいセルを作成するのではなく、セルを再利用していることはかなり確信しています。そのため、ElementGenerated イベントは再び発生せず、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);
                    }
                }
            }
        }
    }
4

1 に答える 1