如何显示交替对齐的行?

How can I display rows with alternating aligning?

我想用这张图片实现类似的效果:

交替对齐的行 - 当行索引为偶数时左对齐,当行索引不均匀时右对齐。

我尝试使用 ListBoxListBox,与 ObservableCollection<ObservableCollection<Circle>> 绑定。我是否应该绑定第二个 ListBoxMargin 属性 以实现交替对齐?

<ListBox
  Name="OuterListBox"
  HorizontalAlignment="Center"
  VerticalAlignment="Center"
  Background="White"
  BorderThickness="0"
  ItemsSource="{Binding Board}">
  <ListBox.ItemTemplate>
    <DataTemplate>
      <Grid>
        <ListBox
          Name="InnerListBox"
          HorizontalAlignment="{Binding HorizontalAlignment}"
          Background="Transparent"
          BorderThickness="0"
          ItemContainerStyle="{StaticResource ChangeListViewItemHighlight}"
          ItemsSource="{Binding}"
          PreviewKeyDown="InnerListBox_PreviewKeyDown">
          <ListBox.ItemTemplate>
            <DataTemplate>
                <Ellipse
                  Width="{Binding Size}"
                  Height="{Binding Size}"
                  Cursor="Hand"
                  Fill="{Binding Background}" />
            </DataTemplate>
          </ListBox.ItemTemplate>
        </ListBox>
      </Grid>
    </DataTemplate>
  </ListBox.ItemTemplate>
</ListBox>

关于您的要求,我根据您提供的示例假设:

  • 有多行。
  • 每一行都有相同数量的项目(圆圈,这里是 5 个)。
  • 所有项目(圆圈)的大小相同。

这样,您只需几步即可使用内置功能实现所需的行为。

  • 更改内部 ListBox 中的 ItemsPanel 以水平显示项目(圆圈)(作为一行)
  • 设置一个2AlternationCount到外ListBox,所以有两个交替索引。
  • 为输出 ListBox 创建一个项目容器样式,它在左侧设置一个 Padding(或 Margin,如果你想要的话)宽度的一半AlternationIndex 0 and the same on the right otherwise. You can create an instance of the already existing AlternationConverter 定义 Paddings.

在这个例子中,填充是固定大小的(对我来说,圆的大小是 50,所以填充是 25)。您还可以创建一个自定义值转换器以使其更具动态性,绑定真实的 Size.

<ListBox
   Name="OuterListBox"
   AlternationCount="2"
   HorizontalAlignment="Center"
   VerticalAlignment="Center"
   Background="White"
   BorderThickness="0"
   ItemsSource="{Binding Board}">
   <ListBox.ItemContainerStyle>
      <Style TargetType="{x:Type ListBoxItem}" BasedOn="{StaticResource {x:Type ListBoxItem}}">
         <Style.Resources>
            <AlternationConverter x:Key="AlternationPaddingConverter">
               <Thickness Right="25"/>
               <Thickness Left="25"/>
            </AlternationConverter>
         </Style.Resources>
         <Setter Property="Padding" Value="{Binding (ItemsControl.AlternationIndex), RelativeSource={RelativeSource Self}, Converter={StaticResource AlternationPaddingConverter}}"/>
      </Style>
   </ListBox.ItemContainerStyle>
   <ListBox.ItemTemplate>
      <DataTemplate>
         <Grid>
            <ListBox
               Name="InnerListBox"
               Background="Transparent"
               BorderThickness="0"
               ItemContainerStyle="{StaticResource ChangeListViewItemHighlight}"
               ItemsSource="{Binding}"
               PreviewKeyDown="InnerListBox_PreviewKeyDown">
               <ListBox.ItemsPanel>
                  <ItemsPanelTemplate>
                     <VirtualizingStackPanel Orientation="Horizontal"/>
                  </ItemsPanelTemplate>
               </ListBox.ItemsPanel>
               <ListBox.ItemTemplate>
                  <DataTemplate>
                     <Ellipse
                        Width="{Binding Size}"
                        Height="{Binding Size}"
                        Cursor="Hand"
                        Fill="{Binding Background}" />
                  </DataTemplate>
               </ListBox.ItemTemplate>
            </ListBox>
         </Grid>
      </DataTemplate>
   </ListBox.ItemTemplate>
</ListBox>


Additional question: how can I remove the highlight of the selected line?

在这个简单的例子中,您可以使用 ItemsControl 作为外部控制而不是 ListBox。它没有选择。但是,您必须设置 ContentPresenter 的样式,然后使用 Margin

<ItemsControl
   Name="OuterListBox"
   AlternationCount="2"
   HorizontalAlignment="Center"
   VerticalAlignment="Center"
   Background="White"
   BorderThickness="0"
   ItemsSource="{Binding Board}">
   <ItemsControl.ItemContainerStyle>
      <Style TargetType="{x:Type ContentPresenter}">
         <Style.Resources>
            <AlternationConverter x:Key="AlternationPaddingConverter">
               <Thickness Right="25"/>
               <Thickness Left="25"/>
            </AlternationConverter>
         </Style.Resources>
         <Setter Property="Margin" Value="{Binding (ItemsControl.AlternationIndex), RelativeSource={RelativeSource Self}, Converter={StaticResource AlternationPaddingConverter}}"/>
      </Style>
   </ItemsControl.ItemContainerStyle>
   <ItemsControl.ItemTemplate>
      <DataTemplate>
         <Grid>
            <ListBox
               Name="InnerListBox"
               Background="Transparent"
               BorderThickness="0"
               ItemContainerStyle="{StaticResource ChangeListViewItemHighlight}"
               ItemsSource="{Binding}"
               PreviewKeyDown="InnerListBox_PreviewKeyDown">
               <ListBox.ItemsPanel>
                  <ItemsPanelTemplate>
                     <VirtualizingStackPanel Orientation="Horizontal"/>
                  </ItemsPanelTemplate>
               </ListBox.ItemsPanel>
               <ListBox.ItemTemplate>
                  <DataTemplate>
                     <Ellipse
                        Width="{Binding Size}"
                        Height="{Binding Size}"
                        Cursor="Hand"
                        Fill="{Binding Background}" />
                  </DataTemplate>
               </ListBox.ItemTemplate>
            </ListBox>
         </Grid>
      </DataTemplate>
   </ItemsControl.ItemTemplate>
</ItemsControl>