3

我创建了一个继承自 WPF 的自定义画布控件Canvas。我在主窗口中像这样使用它 -

<ScrollViewer
    HorizontalScrollBarVisibility="Auto"
    VerticalScrollBarVisibility="Auto">
    <RTD:RTDesignerCanvas
        Margin="5"
        Background="White"
        x:Name="canvas1"
        Focusable="True"
        AllowDrop="True">
    </RTD:RTDesignerCanvas>
</ScrollViewer>

一切正常,但是当我尝试像这样设置控件的位置时

Canvas.SetTop(item, 200);

滚动条不可见,控件隐藏在某处。有趣的是,如果我向它添加另一个控件,滚动条是可见的,我可以向下滚动以查看前一个控件。

我试着用

base.InvalidateVisual();
base.UpdateLayout();
base.InvalidateArrange();

更改项目后TopLeft但没有任何反应;我是否遗漏了什么或者这是由于某些错误而发生的?

更新

澄清一下,假设我有一个画布,其width,height为 100、100。现在,如果我移动一个控件(已经添加到画布中),Canvas.SetLeft(myControl, 200)那么它将移动到默认情况下不可见的位置,并且滚动条也被禁用,所以没有办法看到该控件。

现在,如果我向 Canvas 添加另一个控件,则 ScrollBars 会正确显示,并且我可以通过滚动查看上一个控件。

4

3 回答 3

8

您是否在自定义 Canvas 中覆盖了MeasureOverride ?Canvas 将始终报告 (0, 0) 的 DesiredSize,因此 ScrollViewer 永远不会认为它需要滚动。

请参阅此 StackOverflow 答案,该答案建议使用 Grid 而不是 Canvas 并使用 Margin 属性进行定位。Grid 将根据其子项的大小和位置报告其大小,因此 ScrollViewer 将知道它需要滚动。

更新:

ScrollViewer 会根据它的要求给它的孩子询问多大的尺寸,并且只有当孩子比 ScrollViewer 大时才需要滚动。为了让它正确滚动,您需要报告一个足够大以包含所有子控件的 DesiredSize。您可以通过像这样覆盖 MeasureOverride 来做到这一点:

protected override Size MeasureOverride(Size constraint)
{
    base.MeasureOverride(constraint);
    var desiredSize = new Size();
    foreach (UIElement child in Children)
    {
        desiredSize = new Size(
            Math.Max(desiredSize.Width, GetLeft(child) + child.DesiredSize.Width),
            Math.Max(desiredSize.Height, GetTop(child) + child.DesiredSize.Height));
    }
    return desiredSize;
}

然而,一个更简单的解决方案是利用 Grid 类已经像这样测量的事实。您可以使用子元素的 Margin 属性来准确定位它们,而不是使用 Canvas.Left 和 Canvas.Top 属性。如果你目前正在做

Canvas.SetLeft(item, 100);
Canvas.SetTop(item, 200);

对于画布中的项目,您可以改为

item.Margin = new Thickness(100, 200, 0, 0);

将其放置在一个单元格网格中的相同位置。

于 2010-06-17T12:58:58.090 回答
1

Quartermeister 的回答帮助我解决了这个问题。

我必须base.InvalidateMeasure()在每次操作后显式使用来刷新画布并使滚动条可见。

于 2010-07-01T13:55:01.267 回答
0

阿克乔希,

它必须是一个错误。下次画布隐藏在某个地方时,在其上运行Snoop,并检查它的位置。确保检查以下画布属性:ActualWidth, ActualHeight, Opacity,Visibility

于 2010-06-17T12:59:54.017 回答