WPF自定义FrameworkElement / IScrollInfo

3
我有一个简单的测试应用程序,其中包含一个基本的自定义FrameworkElement实现(下面是TestElement)。TestElement创建了几个绘图可视化对象,并在构造函数中绘制了一些东西,宽度为600。它还实现了IScrollinfo的必要部分; 包含该元素的窗口具有scrollviewer和最大尺寸为300x300。滚动条出现了,但无法滚动TestElement的内容。
请问是否有人能够建议我是否可能实现这个功能,如果可以的话,我应该怎么做才能做对。我可以在SetHorizontalOffset中重新渲染绘图可视化对象,但由于我已经绘制了所有需要的东西,因此不希望这样做以提高性能。
希望问题有一定的意义 - 如果没有,请告诉我,我可以澄清。
非常感谢 - Karl
public class TestElement : FrameworkElement, IScrollInfo
{
    DrawingVisual visual;
    DrawingVisual visual2;
    public TestElement()
    {
        Draw();
        this.MaxWidth = 600;
        this.MaxHeight = 300;
    }
    public void Draw()
    {
        if(visual == null)
        {
            visual = new DrawingVisual();
            base.AddVisualChild(visual);
            base.AddLogicalChild(visual);
        }
        if (visual2 == null)
        {
            visual2 = new DrawingVisual();
            base.AddVisualChild(visual2);
            base.AddLogicalChild(visual2);
        }
        Random rand = new Random();
        var pen = new Pen(Brushes.Black, 1);
        using(var dc = visual.RenderOpen())
        {
            for (int i = 0; i < 400; i++) 
            {
                var r = rand.Next(10, 200);
                dc.DrawLine(pen, new Point(i, r), new Point(i, 0));
            }
        }
        using (var dc = visual2.RenderOpen())
        {
            for (int i = 0; i < 200; i++)
            {
                var r = rand.Next(10, 200);
                dc.DrawLine(pen, new Point(i, r), new Point(i, 0));
            }
            visual2.Offset = new Vector(400, 0);
        }
    }
    protected override int VisualChildrenCount 
    {
        get { return 2; }
    }
    protected override Visual GetVisualChild(int index)
    {
        return index == 0 ? visual : visual2;
    }
    protected override Size MeasureOverride(Size availableSize)
    {
        viewport = availableSize;
        owner.InvalidateScrollInfo();
        return base.MeasureOverride(availableSize);
    }
    protected override Size ArrangeOverride(Size finalSize)
    {
        var value = base.ArrangeOverride(finalSize);
        return base.ArrangeOverride(finalSize);
    }


    Point offset = new Point(0,0);
    public void SetHorizontalOffset(double offset)
    {
        this.offset.X = offset;
        this.InvalidateArrange();
    }

    public void SetVerticalOffset(double offset)
    {
        this.offset.Y = offset;
    }

    public Rect MakeVisible(Visual visual, Rect rectangle)
    {
        throw new NotImplementedException();
    }

    public bool CanVerticallyScroll { get; set; }
    public bool CanHorizontallyScroll { get; set; }

    Size extent = new Size(600, 300);

    private Size viewport = new Size(0, 0);
    public double ExtentWidth
    {
        get { return extent.Width; }
    }

    public double ExtentHeight
    {
        get {return extent.Height; }
    }

    public double ViewportWidth
    {
        get { return viewport.Width; }
    }

    public double ViewportHeight
    {
        get { return viewport.Height; }
    }

    public double HorizontalOffset
    {
        get { return offset.X; }
    }

    public double VerticalOffset
    {
        get { return offset.Y; }
    }

    private ScrollViewer owner;

    public ScrollViewer ScrollOwner
    {
        get { return owner; }
        set { owner = value; }
    }


}

XAML:

<Window x:Class="TestWpfApp.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:l ="clr-namespace:TestWpfApp"
Title="TestWpfApp" Height="300" Width="300" >
<Grid>
    <ScrollViewer CanContentScroll="True" HorizontalScrollBarVisibility="Visible">
        <l:TestElement CanHorizontallyScroll="True" />
    </ScrollViewer>
</Grid>

1个回答

2

我也喝了一杯啤酒,它有助于找到解决方案。;-)

这不是终极的“万事大吉”解决方案,但肯定会帮助你进一步:

在你的ArrangeOverride实现中,请尝试:

protected override Size ArrangeOverride(Size finalSize)
{
    this.visual.Offset = new Vector(-this.HorizontalOffset, -this.VerticalOffset);

    var value = base.ArrangeOverride(finalSize);
    return base.ArrangeOverride(finalSize);
}

基本上你需要自己移动你的对象。

更多信息请参见此文章:iscrollinfo教程。 通常情况下,您需要使用转换来将对象移动到您滚动它们的位置。


嗨 - 感谢回复。是的,那个方法可行(实际上我尝试过类似的方法,但由于某些原因我无法使其工作),但我同意它不感觉像是“完美”的解决方案。此外,我需要为此进行大量的抵消记账,因为我需要的内容将具有多个绘图视觉效果,每个效果都有不同的偏移量。我会再等一段时间看看是否有其他补充,然后我会接受这个解决方案。 - kjn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接