2010-01-22 50 views
16

我有一个简单的WrapPanel其中包含一些广泛的控制。当我调整WindowWidth时,一切正常。如果有足够的空间,则控件将在单行上传递,或者在没有足够空间时包装到下一行。WPF包装面板和滚动

但是,我需要发生的是,如果所有的控件基本上是垂直堆叠的(因为没有更多的水平空间)并且WindowWidth降低得更多,所以会出现一个水平滚动条,可以滚动并查看整个控件,如果我想。以下是我的xaml。我试图用WrapPanel包装ScrollViewer,但我无法实现我的目标。

<Window x:Class="WpfQuotes.Window1" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="Window1" Height="Auto" Width="600" Foreground="White"> 
    <WrapPanel> 
     <Button Width="250">1</Button> 
     <Button Width="250">2</Button> 
     <Button Width="250">3</Button> 
    </WrapPanel> 
</Window> 

所以,如果你减少以上Window到最小的Width,你将无法看到按钮的文本。我想要一个水平滚动条出现,这样我就可以滚动查看文本,但不会干扰通常的包装功能。

谢谢。

更新: 我跟着保罗的建议下面和水平滚动条出现如预期现在。不过,我也想垂直滚动,所以我设置了VerticalScrollBarVisibility="Auto"。问题是,如果我调整窗口大小以使垂直滚动条出现,即使不需要水平滚动条(水平空间足以查看整个控件),也会始终显示水平滚动条。看起来似乎垂直滚动条出现了与scrollviewer的宽度混乱。有没有办法纠正这个问题,除非实际需要水平滚动条?

下面是我的XAML和我在CustomWrapPanel添加的唯一代码:

<Window x:Class="Window1" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:cwp="clr-namespace:CustomWrapPanelExample" 
     Title="Window1" Height="Auto" Width="300" Foreground="White" Name="mainPanel"> 
    <ScrollViewer x:Name="MyScrollViewer" HorizontalScrollBarVisibility="Auto" 
       VerticalScrollBarVisibility="Auto"> 
    <cwp:CustomWrapPanel Width="{Binding ElementName=MyScrollViewer, Path=ActualWidth}"> 
     <Button Width="250">1</Button> 
     <Button Width="250">2</Button> 
     <Button Width="250">3</Button> 
     <Button Width="250">4</Button> 
     <Button Width="250">5</Button> 
     <Button Width="250">6</Button> 
     <Button Width="250">7</Button> 
     <Button Width="250">8</Button> 
     <Button Width="250">9</Button> 
    </cwp:CustomWrapPanel> 
    </ScrollViewer> 
</Window> 

CustomWrapPanel覆盖的唯一的事:

protected override Size MeasureOverride(Size availableSize) 
{ 
    double maxChildWidth = 0; 
    if (Children.Count > 0) 
    { 
    foreach (UIElement el in Children) 
    { 
     if (el.DesiredSize.Width > maxChildWidth) 
     { 
     maxChildWidth = el.DesiredSize.Width; 
     } 
    } 
    }  
    MinWidth = maxChildWidth; 
    return base.MeasureOverride(availableSize); 
} 
+0

你可以用ScrollViewer发布XAML吗? – hackerhasid 2010-01-22 17:26:36

回答

43

事情是这样的,如果你要使用一个包它会做两件事,它将占用一个方向上的可用空间,并在另一方面根据需要扩展。例如,如果将它放置在窗口内部,就像它拥有它一样,它占用尽可能多的水平空间,然后根据需要向下扩展,这就是垂直滚动条工作的原因,父容器说“这是我有多宽,但是你可以让自己像垂直想要的那样大“,如果你把它改成水平滚动条,那么滚动查看器本质上是说”这可能会有多高,但你可以像你想要“在这种情况下,包装面板不会换行,因为没有水平约束。

一个潜在的解决办法是改变画布面板从水平换到垂直这样的方向(这可能不是理想的或预期的行为):

<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Disabled"> 
     <WrapPanel Orientation="Vertical"> 
      <Button Width="250">1</Button> 
      <Button Width="250">2</Button> 
      <Button Width="250">3</Button> 
     </WrapPanel> 
    </ScrollViewer> 

为了让您的期望的行为,你必须做一些接近这个:

<ScrollViewer x:Name="MyScrollViewer" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Disabled"> 
     <WrapPanel MinWidth="250" Width="{Binding ElementName=MyScrollViewer, Path=ViewportWidth}"> 
      <Button Width="250">1</Button> 
      <Button Width="250">2</Button> 
      <Button Width="250">3</Button> 
     </WrapPanel> 
    </ScrollViewer> 

但是,如果你已经知道你的孩子元素的宽度第二种解决方案仅适用,最好你希望你的最大宽度设置为实际宽度最大的儿童项目,但在o为了做到这一点,你必须创建一个自定义控件,它可以从wrap面板派生出来并自己编写代码来检查它。

+0

谢谢保罗。我按照你所描述的做了改变,现在它运行得更好。但是,我看到一个小问题w.r.t.垂直滚动。我还想要一个垂直滚动条出现,只要包装面板的项目不完全可见垂直。我编辑了我原来的帖子,以显示我所做的更改以及我面临的问题。 – Flack 2010-01-22 19:14:00

+0

Ahh ...玩了一下,你所需要做的就是将包装面板上的绑定路径从ActualWidth更改为ViewportWidth,当垂直滚动条被添加时,它使得视口宽度更小,尽管实际控制保持相同的尺寸。这应该解决你看到的奇怪的水平滚动条错误,我会更新我的帖子。 – 2010-01-22 21:39:42

+0

优秀!它现在看起来很完美。非常感谢您的帮助:) – Flack 2010-01-22 21:52:52