WPF Wrap Panel и прокрутка - PullRequest
       15

WPF Wrap Panel и прокрутка

20 голосов
/ 22 января 2010

У меня есть простой 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". Дело в том, что если я изменю размер окна так, чтобы появилась вертикальная полоса прокрутки, горизонтальная также всегда появляется, даже если она не нужна (достаточно горизонтального пространства, чтобы увидеть весь элемент управления). Кажется, что вертикальная полоса прокрутки пересекается с шириной прокрутки. Есть ли способ исправить это так, чтобы горизонтальная полоса прокрутки не появлялась, если она действительно не нужна?

Ниже мой 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 Ответ

47 голосов
/ 22 января 2010

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

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

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

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

...