WPF包装面板和滚动

Fla*_*ack 21 c# wpf scroll wrappanel

我有一个简单的WrapPanel包含许多宽控件.当我调整大小Width时,Window一切按预期工作.如果有足够的空间,控件将在一行上进行,或者如果没有,则控件将在下一行中包含.

但是,我需要发生的是,如果所有控件基本上都是垂直堆叠的(因为没有更多的水平空间)并且其中WidthWindow更多还是更多,则会出现一个水平滚动条,以便我可以滚动并查看整个控制我是否愿意.下面是我的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>
Run Code Online (Sandbox Code Playgroud)

因此,如果Width将上述内容减少Window到最小值,您将无法看到按钮的文本.我想要一个水平滚动条出现,以便我可以滚动查看文本,但不会干扰通常的包装功能.

谢谢.

更新: 我已按照下面的保罗建议,水平滚动条现在按预期显示.但是,我也希望垂直滚动可用,所以我设置VerticalScrollBarVisibility="Auto".问题是,如果我调整窗口大小以便显示垂直滚动条,即使不需要(也有足够的水平空间来查看整个控件),也会始终显示水平滚动条.好像出现的垂直滚动条会弄乱滚动查看器的宽度.有没有办法纠正这个问题,除非实际需要水平滚动条,否则不会出现?

下面是我的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>
Run Code Online (Sandbox Code Playgroud)

唯一被覆盖的事情是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);
}
Run Code Online (Sandbox Code Playgroud)

Pau*_*hde 51

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

一个可能的解决方案是改变包裹面板从水平到垂直的方向,这样(这可能不是理想或预期的行为):

    <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>
Run Code Online (Sandbox Code Playgroud)

为了获得您期望的行为,您将不得不做更接近这一点的事情:

    <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>
Run Code Online (Sandbox Code Playgroud)

但是,第二个解决方案只有在您已经知道子元素的宽度时才有效,理想情况下您希望将最大宽度设置为最大子项的实际宽度,但为了做到这一点,您必须创建一个自定义控件派生自包装面板并自己编写代码以检查它.


Ely*_*755 6

这是我的解决方案:

    <Grid Width="475">
        <ItemsControl ItemsSource="{Binding Items}" 
                          Height="450" Width="475" >

            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <local:HorizontalListItemControl />
                </DataTemplate>
            </ItemsControl.ItemTemplate>

            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <WrapPanel />
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>

            <ItemsControl.Template>
                <ControlTemplate>
                    <ScrollViewer>
                        <ItemsPresenter />
                    </ScrollViewer>
                </ControlTemplate>
            </ItemsControl.Template>

        </ItemsControl>
    </Grid>
Run Code Online (Sandbox Code Playgroud)



我将尝试解释:
我使用了 ItemsControl,它的 ItemsSource 绑定到我的 Items 集合。在其中,我将 WrapPanel 定义为 ItemsPanelTemplate。这就是完成包装工作的原因。

            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <WrapPanel />
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
Run Code Online (Sandbox Code Playgroud)


但现在,没有滚动了,对吧?
为了解决这个问题,我在 ScrollViewer 中定义了一个 ItemsPresenter 作为 ControlTemplate:

            <ItemsControl.Template>
                <ControlTemplate>
                    <ScrollViewer>
                        <ItemsPresenter />
                    </ScrollViewer>
                </ControlTemplate>
            </ItemsControl.Template>
Run Code Online (Sandbox Code Playgroud)


现在您可以滚动了。



希望我有所帮助。