如何在 ScrollViewer 中获得 Adorner 与其装饰元素的一对一匹配?

Posted

技术标签:

【中文标题】如何在 ScrollViewer 中获得 Adorner 与其装饰元素的一对一匹配?【英文标题】:How to get a one-to-one match of an Adorner with its adorned element within a ScrollViewer? 【发布时间】:2017-04-26 16:55:05 【问题描述】:

wpf

我在 ScrollViewer 的 Grid 中有一个控件 A(一个 inkcanvas)。控件 A 比物理窗口高,因此 ScrollViewer 正确添加了垂直滚动条,向下滚动可以查看整个控件。将带有控件 B 的装饰器(另一个 inkcanvas)附加到控件 A 时,向下滚动会在屏幕底部显示要切断的装饰器。也就是说,Adorner 没有完全覆盖被装饰的元素和/或在滚动时没有向下延伸。

如何让 Adorner(控件)完全覆盖被装饰的元素并尊重 ScrollViewer。 (我需要在 Adorner 控件的像素和 ScrollViewer 中的装饰元素之间进行一对一的匹配)。

TIA

Edit#1:Adorner 中设置 InkCanvas 背景的关键行是

_inkcanvas.Background = CreateGrid();

public InkCanvasTextAdorner(InkCanvas element) 
            : base(element)
        
            _element = element;

            _visuals = new VisualCollection(this);
            _inkcanvas = new InkCanvas();

            _inkcanvas.Background = CreateGrid();

            _visuals.Add(_inkcanvas);   

            AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(element);
            adornerLayer.Add(this);
        

如果使用 InkCanvas(如上所述),则 Adorner 的 背景 会在底部被剪裁。但是,装饰器控件确实会继续到被装饰元素的底部。

但是,如果使用 Canvas 而不是 InkCanvas,则 Adorner 的 背景 会延伸到被装饰元素的底部。

怎么了?

【问题讨论】:

【参考方案1】:

我猜测 Background 属性的差异通过 Canvas 而不是 InkCanvas 扩展到物理屏幕可能是因为 Canvas 继承自 Panel 而 InkCanvas 没有。根据发现 Canvas 背景确实可以满足我的需要,我发现下面的代码确实实现了我想要的功能 - 画布允许看到来自其下方图层的图像,但发布了一个网格线,InkCanvas 将在该网格上接受笔划。一切都很好:)

public InkCanvasTextAdorner(InkCanvas element) 
            : base(element)
        
            _element = element;

            // The VisualCollection has only one visual parent.  I.e. InkCanvasTextAdorner is the parent to the VisualCollection.
            // By overriding default rendering behavior of the VisualCollection, any kind of control and its children can be placed in the Adorner. 
            _visuals = new VisualCollection(this);
            _inkcanvas = new InkCanvas();
            _inkcanvas.Background = Brushes.Transparent;

            _canvas = new Canvas();
            _canvas.Background = CreateGrid();

            _grid = new Grid();
            _grid.Children.Add(_canvas);
            _grid.Children.Add(_inkcanvas);

            // The _grid is a logical child of the VisualCollection of the Adorner. The ArrangeOverride and MeasureOverride will set up the Grid control.
            _visuals.Add(_grid);   // Adding a single control for display.

            // AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(element);
            AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(element);
            adornerLayer.Add(this);
        

看起来像:

【讨论】:

以上是关于如何在 ScrollViewer 中获得 Adorner 与其装饰元素的一对一匹配?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 ListBox 中禁用 ScrollViewer?

如何在ListBox中禁用ScrollViewer?

如何在 ScrollViewer (ListView) 中查找项目的位置?

如何让 ScrollViewer 在 StackPanel 中工作?

如何在 Blend 的设计时滚动 ScrollViewer

如何防止 ScrollViewer 在更新时触发 ViewChanged 事件?