列表框项目中的第一个元素与第二个元素重叠

First Element in list box item is overlapping the second element

我有一个列表框,每个列表框项都包含一个带有两个元素 TextBlock 和一个标签的 DockPanel。以下是 xaml 代码 -

        <ListBox HorizontalContentAlignment="Stretch" ScrollViewer.HorizontalScrollBarVisibility="Disabled">
           <ListBoxItem>
            <DockPanel>
                <TextBlock Text="Ted its so wonderfull I am gere asdf asdf asdf adsf asdf asdf asdfasf asfd asf asdf asdf asdf asdf asdasfd asf " TextWrapping="Wrap"></TextBlock>
                <Label Content="Click Me" HorizontalAlignment="Right"></Label>
            </DockPanel>                
        </ListBoxItem>

        <ListBoxItem>
            <DockPanel>
                <TextBlock Text="Ted its so wonderfull Ted its so wonderfull I am gere asdf asdf asdf adsf asdf asdf asdfasf asfd asf asdf asdf asdf asdf asdasfd asf" TextWrapping="Wrap"></TextBlock>
                <Label Content="Click Me" HorizontalAlignment="Right"></Label>
            </DockPanel>
        </ListBoxItem>
    </ListBox>

所以我期待 window 每行都有两个元素,第一列是文本块,下一个是标签。我为标签添加了 Horizo​​natalContentAlignment=stretch 和 Horizo​​ntalAlignment=Right,以便当用户调整 window 大小时标签应位于右端。

但是我在上面的代码中遇到的问题是,当我调整 window 的大小时,当文本块开始换行时,Textblock 是 hiding/overlapping 标签元素。在某些情况下,标签完全隐藏,当文本块中的单词与 window 的右端完美对齐时,或者部分隐藏 ?

为什么第二个元素重叠或隐藏了?我想始终显示“点击我”标签,如何实现?

您可以使用网格。第一列使用所有可用的 space,其中第二列为 'click' 标签保留 space。

        <ListBoxItem>
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*"></ColumnDefinition>
                    <ColumnDefinition Width="Auto"></ColumnDefinition>
                </Grid.ColumnDefinitions>
                <TextBlock Text="Ted its so wonderfull I am gere asdf asdf asdf adsf asdf asdf asdfasf asfd asf asdf asdf asdf asdf asdasfd asf " TextWrapping="Wrap"></TextBlock>
                <Label Grid.Column="1" Content="Click Me" HorizontalAlignment="Right"></Label>
            </Grid>
        </ListBoxItem>

下图显示了与停靠方法相比的网格。

只是要指出,在其他场景中,例如未知数量的元素要添加到ListBoxItem内容中例如,使用 DockPanel 还不错。

示例:

  • ListBox 中的第一项,我想要一个 Text 和一个 Label
  • 第二件,我想要一个Text,一个Label 和一个Button
  • 等等...

有了 Grid,除非您添加很多东西(使用 ContentTemplate 和绑定,甚至代码隐藏),否则它不会工作,这就是 DockPanel 有用的地方。

您的方法的错误在于您将 TextBlock 放在了 Label 之前。在 DockPanel 中,顺序很重要,第一个项目优先于第二个项目,第二个项目优先于第三个项目......如果前一个项目已经占用了所有剩余的 space(你的 TextBlock 用它很长的 Text 值) 那么后面的任何其他项目都不会按预期绘制。

并且不要忘记指定 Docking 模式。

所以,为了澄清起见,在这里使用 DockPanel 没有任何问题,但项目顺序很重要。

<ListBox HorizontalContentAlignment="Stretch" 
    ScrollViewer.HorizontalScrollBarVisibility="Disabled">
    <ListBoxItem>
        <DockPanel>
            <!-- Declare your Label first and dock it to the right -->
            <Label 
                DockPanel.Dock="Right" />
            <TextBlock 
                Text="Ted its so wonderfull I am gere asdf asdf asdf adsf asdf asdf asdfasf asfd asf asdf asdf asdf asdf asdasfd asf " TextWrapping="Wrap" />
        </DockPanel>                
    </ListBoxItem>

    <!-- ... -->

</ListBox>

有些 UIElement 像 Label 在 Left/Right 停靠在 DockPanel 中时并不(真的)需要 HorizontalAlignment。在这种情况下, VerticalAlignment 重要。

规则是:

  • 请记住,DockPanel 会为每个项目分配一个矩形 区域。
  • 项目按顺序获得分配的区域。
  • DockPanel 默认停靠在左侧。
  • DockPanel 更好地处理占据小区域的项目列表,这些项目声明为 first 并相应地停靠,然后 last 项目如果可用,将填充剩余 space 的可变大小。
  • 当可用区域不够宽时,DockPanel 将始终尝试至少显示每个项目的一小部分(因此,当您希望项目保持完全可见时,请仔细添加约束,例如将 DockPanel 网格列或行中 ;) )

In the end, this is an answer that explains why the Label is overlapped by the TextBlock – for other readers wanting to master a DockPanel.

But yeah, when I already know how many items I'm going to have in a container, I'll use a Grid, 99% of the time, because I can bind Row and Columns size directly, while with a DockPanel, StackPanel, etc, I would have to reference each contained item one by one.

I do agree with the accepted answer :)