代码之家  ›  专栏  ›  技术社区  ›  akjoshi HCP

更改画布中控件的位置后,滚动条不可见。

  •  2
  • akjoshi HCP  · 技术社区  · 14 年前

    我创建了一个继承自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();
    

    更改项目后 Top Left 但是什么都没有发生;我是错过了什么,还是因为一些错误而发生了这种情况?

    更新 :

    为了澄清,假设我有一幅画布 width , height 为100, 100。现在,如果移动控件(已添加到画布中),请使用 Canvas.SetLeft(myControl, 200) 然后它将移动到默认情况下不可见的位置,滚动条也被禁用,因此无法看到该控件。

    现在,如果我向画布中添加另一个控件,滚动条就会正确显示,我可以通过滚动查看上一个控件。

    3 回复  |  直到 11 年前
        1
  •  7
  •   Community c0D3l0g1c    7 年前

    你覆盖了吗 MeasureOverride 在你的定制画布上?Canvas将始终报告所需的大小(0,0),因此ScrollViewer不会认为需要滚动。

    this StackOverflow answer 建议使用网格而不是画布,并使用Margin属性进行定位。网格将根据子网格的大小和位置报告其大小,因此ScrollViewer将知道它需要滚动。

    更新:

    ScrollViewer将为其子级提供所需的大小,并且仅当子级大于ScrollViewer时才需要滚动。为了使其正确滚动,您需要报告一个所需的大小,该大小足以包含所有子控件。您可以通过这样覆盖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;
    }
    

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

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

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

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

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

        2
  •  1
  •   akjoshi HCP    11 年前

    四分之一的回答帮助我解决了这个问题。

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

        3
  •  0
  •   Anvaka    14 年前

    Akjoshi

    一定是个虫子。下次画布隐藏时,请运行 Snoop 在上面,检查它在哪里。确保检查以下画布属性: ActualWidth , ActualHeight , Opacity , Visibility