如何使 DockPanel 填充可用空间

Posted

技术标签:

【中文标题】如何使 DockPanel 填充可用空间【英文标题】:How to make DockPanel fill available space 【发布时间】:2010-11-08 00:07:31 【问题描述】:

我正在尝试ItemsControl(ListBox) 中的购物车内容。为此,我创建了以下DataTemplate

<DataTemplate x:Key="Templates.ShoppingCartProduct"
              DataType="x:Type viewModel:ProductViewModel">
    <DockPanel HorizontalAlignment="Stretch">
        <TextBlock DockPanel.Dock="Left"
                   Text="Binding Path=Name"
                   FontSize="10"
                   Foreground="Black" />
        <TextBlock DockPanel.Dock="Right"
                   Text="Binding Path=Price, StringFormat=\0:C\"
                   FontSize="10"
                   Foreground="Black" />
    </DockPanel>
</DataTemplate>

当商品显示在我的购物车中时,名称和价格TextBlocks 并排放置,右侧有大量空白。

想知道强制DockPanel 伸展以填充ListItem 提供的所有可用空间的最佳方法是什么?

【问题讨论】:

【参考方案1】:

DockPanelWidth绑定到ListBoxItemActualWidth

<DockPanel Width="Binding ActualWidth, RelativeSource=RelativeSource FindAncestor, AncestorType=x:Type ListBoxItem">
...

另一种选择:您可以重新定义ItemContainerStyle,使ListBoxItem 水平拉伸:

<ListBox.ItemContainerStyle>
    <Style TargetType="ListBoxItem">
        <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
    </Style>
</ListBox.ItemContainerStyle>

【讨论】:

我尝试使用该绑定,它似乎导致 ListBoxItem 的大小不断增长,当使用 Snoop 查看时,我看到 ListBoxItem 和 DockPanel 的宽度都超过了 300,000。 哦,好的,我明白了...你必须在DockPanel上设置LastChildFill="False",否则第二个TextBlock被拉伸 我最终找到了您的第二种方法并走那条路线。 如果您使用 Horizo​​ntalContentAlignment 而不是 Horizo​​ntalAlignment,则第二种方法有效。我编辑了答案。 如果您的 ListBox 被缩小,第一种方法不起作用。实际大小保持在最大值。【参考方案2】:

停靠面板的好处是它们已经填满了所有可用空间。 LastChildFill 默认为 true(但为了清楚起见,我在下面设置了它),所以不要在最后一个孩子上设置 DockPanel 属性,它会填充可用空间。

<DockPanel HorizontalAlignment="Stretch" LastChildFill="true">
    <TextBlock DockPanel.Dock="Left"
               Text="Binding Path=Name"
               FontSize="10"
               Foreground="Black" />
    <TextBlock 
               Text="Binding Path=Price, StringFormat=\0:C\"
               FontSize="10"
               Foreground="Black" />
</DockPanel>

【讨论】:

【参考方案3】:

DockPanels 是邪恶的。将StackPanel/DockPanel 组合用于复杂布局的诱惑会导致“布局死胡同”。使用网格:

<Grid>
  <TextBlock HorizontalAlignment="Left"
...
  <TextBlock HorizontalAlignment="Right"
...
/Grid>

我几乎只使用Grids,为每个“属于一起”的元素块使用单独的网格

【讨论】:

我不认为 DockPanel 是邪恶的,它们有时会非常有用......但我必须同意,在这种情况下它可能不是最好的选择 当然这是主观的,它们不是 绝对 邪恶;)但是看看 Rich 已经去哪里了 - 使用 ItemContainerStyle(半高级的东西)来完成简单的任务 - 有点指示性... 我一开始就考虑过网格。但是,如果 ListBox 很窄,或者 Name 或 Price 属性的值足够长,两个 TextBlock 最终会重叠它们的值。此外,我很难将在面板两端放置两个 TextBlock 归类为“复杂布局”。 很抱歉对这篇旧帖子发表评论,但使用网格也是解决问题的简单且同样有效的解决方案。重叠问题是可以避免的。 +1 这是一个旧答案,但我想我要指出的是,在 ListBox 的项目模板中使用网格或面板的问题在于它不是一个单一的元素;它是每个 ListBoxItem 的新元素,除非在模板中明确设置,否则它不会共享其他项的宽度。这使得在使用动态宽度时将 ItemContainerStyle 内容对齐设置为拉伸是必要的。

以上是关于如何使 DockPanel 填充可用空间的主要内容,如果未能解决你的问题,请参考以下文章

如何使 DockPanel 中的项目扩展以适应 WPF 中的所有可用空间?

wpf DockPanel默认填充机制

如何使下一个/图像填充可用的网格空间?

如何使wpf数据网格填充所有可用空间并使用窗口调整大小?

如何使TextBox填充所有可用空间而不稍后调整其内容?

使 QListWidget 调整其项目的大小以填充空间