在Canvas中更改控件的位置后,ScrollBars不可见 [英] ScrollBars are not visible after changing positions of controls inside a Canvas

查看:169
本文介绍了在Canvas中更改控件的位置后,ScrollBars不可见的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

 < ScrollViewer 
Horizo​​ntalScrollBarVisibility =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();改变项目后顶部或<$ c>后,

$ c> Left 但什么也没有发生;


$ b

更新

>澄清,说我有一个画布,其 width height 为100,100.现在如果我移动使用 Canvas.SetLeft(myControl,200)控制(已添加在画布中),然后它将移动到默认情况下不可见的位置,滚动条也被禁用,因此没有办法看到这个控制。



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

解决方案

您是否覆写了 MeasureOverride 在您的自定义画布? Canvas将总是报告一个DesiredSize(0,0),所以ScrollViewer永远不会认为它需要滚动。



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



更新:



ScrollViewer会根据要求向其子女询问大小,如果子项大于ScrollViewer,则滚动。为了使其正常滚动,您需要报告一个足够大以包含所有子控件的DesiredSize。你可以通过覆盖MeasureOverride像这样:

  protected override Size MeasureOverride(Size constraint)
{
base.MeasureOverride(constraint);
var desiredSize = new Size();
foreach(Children中的UIElement child)
{
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);

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

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

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


I created a custom canvas control inheriting from WPF Canvas. I am using it like this in main window -

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

Everything works fine but when I try to set the position of controls inside it like this

Canvas.SetTop(item, 200);

scrollbars are not visible and control is hidden down somewhere. Interestingly, if I add another control to it scroll bars are visible and I can scroll downwards to see the previous control.

I tried to use

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

after changing items Top or Left but nothing happens; Am I missing something or this happens due to some bug?

Update:

to clarify, say I have a canvas having its width, height as 100, 100. Now if I move a control(already added in canvas) using Canvas.SetLeft(myControl, 200) then it will move to a position which is not visible by default and scroll bars are also disabled, so there is no way to see that control.

Now if I add another control to Canvas, ScrollBars appear correctly and I can see the previous control by scrolling.

解决方案

Did you override MeasureOverride in your custom Canvas? Canvas will always report a DesiredSize of (0, 0), so the ScrollViewer will never think it needs to scroll.

See this StackOverflow answer which suggests using a Grid instead of a Canvas and using the Margin property for positioning. The Grid will report its size based on the size and position of its children, so the ScrollViewer will know it needs to scroll.

Update:

ScrollViewer will give its child ask much size as it asks for, and will only need to scroll if the child is larger than the ScrollViewer. In order to have it scroll properly, you'll need to report a DesiredSize that is large enough to include all of your child controls. You can do that by overriding MeasureOverride like this:

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;
}

An easier solution, however, is to take advantage of the fact that the Grid class will already measure like this. You can use the Margin property of the child elements to position them exactly instead of the Canvas.Left and Canvas.Top properties. If you are currently doing

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

for an item in the Canvas, you could instead do

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

to position it in the same place within a one-cell Grid.

这篇关于在Canvas中更改控件的位置后,ScrollBars不可见的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆