Silverlight ItemsPanel - WrapPanel

    <ItemsPanelTemplate x:Key="lbWrapPanelItemsPanelTemplate">
        <wp:WrapPanel Margin="2" Background="Beige" HorizontalAlignment="Stretch">
        </wp:WrapPanel>
    </ItemsPanelTemplate>

.....

<Grid Background="LightCoral" MinWidth="500" MinHeight="500">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="200"></ColumnDefinition>
        <ColumnDefinition Width="*"></ColumnDefinition>
    </Grid.ColumnDefinitions>
    <sdk:GridSplitter Grid.Column="0" Background="AliceBlue" />

    <StackPanel Grid.Column="0" FlowDirection="LeftToRight">
        <Button Width="40">Left</Button>
        <Button Width="40">Right</Button>
    </StackPanel>

    <Grid Background="Bisque" Grid.Column="1">
        <Grid.RowDefinitions>
            <RowDefinition Height="*"></RowDefinition>
            <RowDefinition Height="100"></RowDefinition>
        </Grid.RowDefinitions>

        <ListBox ItemsPanel="{StaticResource lbWrapPanelItemsPanelTemplate}" x:Name="bookListBox" HorizontalAlignment="Stretch"  Grid.Row="0" ItemsSource="{Binding Path=BookSource}" ItemTemplate="{StaticResource dirtSimple}"  />

        <wp:WrapPanel Grid.Row="1">
            <Button Width="200" Command="{Binding Path=AddItemCommand}">Bottom</Button>
            <Button Width="200" Command="{Binding ChangeTemplateCommand}" CommandParameter="{StaticResource vmDataTemplate}">White</Button>
            <Button Width="200" Command="{Binding ChangeTemplateCommand}" CommandParameter="{StaticResource vmDataTemplate2}">Lavender</Button>
        </wp:WrapPanel>
    </Grid>

</Grid>

ListBox работает отлично, за исключением того, что (Beige) WrapPanel, кажется, уходит в бесконечность. По мере добавления дополнительных элементов в ListBox он просто прокручивается вправо, а не обертывается. Если я добавлю конкретный размер к WrapPanel, это заставит вещи обернуться, но (очевидно) заставит элементы в LB отображаться в подмножестве всего доступного пространства.

Есть ли способ указать WrapPanel занять все доступное пространство и не больше?


person Adam Rackis    schedule 21.10.2010    source источник


Ответы (2)


У меня всегда возникают проблемы с правильной работой WrapPanel внутри ListBoxes (вероятно, что-то в шаблоне связано с ScrollViewer в нем). Если вы возьмете свой код и поместите его в ItemsControl вместо ListBox, вы увидите, что он работает как есть.

Вы можете повлиять на ScrollViewer внутри WrapPanel и заставить его обернуть:

<ListBox HorizontalAlignment="Stretch" ItemsSource="{Binding foo}" ScrollViewer.HorizontalScrollBarVisibility="Disabled">
    <ListBox.ItemsPanel>
        <ItemsPanelTemplate>
            <tk:WrapPanel Orientation="Horizontal" />
        </ItemsPanelTemplate>
    </ListBox.ItemsPanel>
</ListBox>

Обратите внимание на ScrollViewer.HorizontalScrollBarVisibility, установленный в ListBox - это предотвращает горизонтальную полосу прокрутки, которая заставляет ваш WrapPanel переноситься.

person Adam Sills    schedule 21.10.2010
comment
Я только что добавил Stretch, но никакого эффекта. Полный XAML есть. Большое спасибо за помощь. - person Adam Rackis; 22.10.2010
comment
Ха - даже если я добавлю Width = 300 в ListBox, он просто создаст крошечный LB шириной 300 пикселей, который все еще прокручивается таким же образом :( - person Adam Rackis; 22.10.2010
comment
Я ненавижу WrapPanel TK. Это единственный контроль, который мне никогда не подходит. У меня есть способ обойти это, но это некрасиво. Дай мне еще минутку :) - person Adam Sills; 22.10.2010
comment
Конечно. По вашему мнению, есть ли лучшие WrapPanels? Как Silverlight 4 не имеет встроенной панели WrapPanel, мне не понятно - person Adam Rackis; 22.10.2010
comment
WrapPanel в TK в порядке, он просто не работает интуитивно в некоторых элементах управления (например, в ListBox), хотя суперкласс ListBox работает так, как вы ожидаете. - person Adam Sills; 22.10.2010
comment
Вы уже сделали все возможное, но знаете ли вы, как написать привязку, чтобы она работала, даже если шаблон записан в разделе «Ресурсы», а не встроен в LB, как у вас? Привязке не нравится ссылка на имя в разделе "Ресурсы". Будет ли работать какая-то привязка к предкам? - person Adam Rackis; 22.10.2010
comment
Не в Silverlight, нет. Вам нужно будет включить ItemsPanelTemplate непосредственно в ListBox, потому что в Silverlight нет привязок предков (только Self и TemplatedParent). - person Adam Sills; 22.10.2010
comment
Ну, вы также можете сделать некоторую забаву, например, прикрепленное свойство, чтобы установить его (используйте помощник VisualTree в обратном вызове изменения свойства, чтобы найти родителя и установить значение таким образом). Но в конечном итоге, вероятно, проще просто включить ItemsPanelTemplate, напрямую применить к нему стиль, который есть в ваших ресурсах. - person Adam Sills; 22.10.2010
comment
Кстати, причина, по которой я хотел иметь это как ресурс, а не встраивать, заключалась в том, что я хотел иметь возможность менять местами его вставку и отключение - вроде как позволить пользователю щелкнуть кнопку и изменить внешний вид LB. Я полагаю, что это невозможно, если вы встроите шаблон в элемент управления. - person Adam Rackis; 22.10.2010
comment
К вашему сведению - посмотрите на ответ еще раз. Я обновил его решением, заставляющим обернуть WrapPanel, отключив горизонтальную полосу прокрутки. - person Adam Sills; 22.10.2010
comment
Надеюсь, это сработает лучше, чем любые другие хакерские решения :) - person Adam Sills; 22.10.2010
comment
Что ж, будь я проклят. Это сработало. Вы бог среди людей, мистер Адам Силлс. Огромное вам спасибо. - person Adam Rackis; 22.10.2010

Вы можете исправить это, привязав ширину WrapPanel к ActualWidth ListBox:

<WrapPanel Width="{Binding RelativeSource={RelativeSource AncestorType=ListBox}, Path=ActualWidth"}

(если, конечно, это не работает только в WPF, а не в Silverlight, чего я не знаю.)

Однако любопытно, почему ListBox делает это, а ItemsControl - нет. У WrapPanel правильные поля, и элементы, которые он содержит, правильно обтеканы на этой странице:

<Page
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <Grid>
    <Grid.ColumnDefinitions>
      <ColumnDefinition Width="700"/>
    </Grid.ColumnDefinitions>
    <ItemsControl 
      Background="Azure"
      Margin="5">
      <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
          <WrapPanel 
            Background="Lavender"
            Margin="10"/>
        </ItemsPanelTemplate>
      </ItemsControl.ItemsPanel>
      <ListBoxItem>adsk flaskjf lkasjd flaskdjf laskdj</ListBoxItem>
      <ListBoxItem>adsk flaskjf lkasjd flaskdjf laskdj</ListBoxItem>
      <ListBoxItem>adsk flaskjf lkasjd flaskdjf laskdj flaksjf laskjf aslkjf alsjkf lsafdkj </ListBoxItem>
      <ListBoxItem>adsk flaskjf lkasjd flaskdjf laskdj flaksjf laskjf aslkjf alsjkf lsafdkj </ListBoxItem>
      <ListBoxItem>adsk flaskjf lkasjd flaskdjf laskdj flaksjf laskjf aslkjf alsjkf lsafdkj </ListBoxItem>
      <ListBoxItem>adsk flaskjf lkasjd flaskdjf laskdj flaksjf laskjf aslkjf alsjkf lsafdkj </ListBoxItem>      
    </ItemsControl>
  </Grid>
</Page>

Измените ItemsControl на ListBox, и этого не произойдет.

person Robert Rossney    schedule 21.10.2010
comment
В Silverlight нет привязки к предку. X работает в WPF, но не в Silverlight, похоже, это обычная тема ... - person Adam Rackis; 22.10.2010