Панель WPF wrap и прокрутка

у меня простой WrapPanel который содержит ряд широких элементов управления. Когда я изменяю размер Width на Window все работает, как ожидалось. Элементы управления будут проходить по одной строке, если есть достаточно места или обернуть к следующей строке, когда нет.

однако, что мне нужно сделать, так это то, что если все элементы управления в основном уложены вертикально (так как нет больше горизонтального пространства) и Width на Window уменьшено даже больше, горизонтальное появится полоса прокрутки, чтобы я мог прокручивать и видеть весь элемент управления, если захочу. Ниже приведен мой 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>

Итак, если вы уменьшите Width выше Window как минимум, вы не сможете увидеть текст кнопок. Я хотел бы, чтобы горизонтальная полоса прокрутки появилась, чтобы я мог прокручивать текст, но не мешать обычной обертке функциональность.

спасибо.

обновление: Я последовал предложению пола ниже, и горизонтальная полоса прокрутки появляется, как и ожидалось. Тем не менее, я также хотел, чтобы вертикальная прокрутка была доступна, поэтому я установил 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);
}

1 ответов


вот что, если вы собираетесь использовать панель обертывания, она делает две вещи, она займет столько свободного места в одном направлении и расширится по мере необходимости в другом. Например, если вы поместите его внутри окна, как у вас есть, он занимает столько горизонтального пространства, сколько может, а затем расширяется по мере необходимости вниз, поэтому вертикальная полоса прокрутки будет работать, родительский контейнер говорит: "Вот насколько я широк, но вы можете сделать себя таким большим, как хотите вертикально" , если вы измените его на горизонтальной полосе прокрутки средство просмотра прокрутки по существу говорит:" Вот как вы можете быть высоким, но вы можете быть таким широким, как хотите " в этом случае панель обертки не обертывается, потому что нет горизонтальных ограничений.

одним из потенциальных решений является изменение направления обертывания панели обертывания с горизонтального на вертикальное (что, вероятно, не является идеальным или ожидаемым поведением):

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

однако это второе решение работает только в том случае, если вы уже знаете ширину ваших дочерних элементов, в идеале вы хотите, чтобы ваша максимальная ширина была установлена на фактическую ширину самого большого дочернего элемента, но для этого вам нужно создать пользовательский элемент управления, производный от панели wrap, и написать код самостоятельно, чтобы проверить это.