【问题标题】:Synchronizing WPF control widths in a WrapPanel在 WrapPanel 中同步 WPF 控件宽度
【发布时间】:2010-11-05 10:17:26
【问题描述】:

我有这个案例

<WrapPanel>
    <CheckBox>Really long name</CheckBox>
    <CheckBox>Short</CheckBox>
    <CheckBox>Longer again</CheckBox>
    <CheckBox>Foo</CheckBox>
    <Slider MinWidth="200" />
</WrapPanel>

我希望 WrapPanel 中的所有 CheckBox 都具有相同的宽度。

添加以下几乎可以达到预期的效果

<WrapPanel.Resources>
    <Style TargetType="CheckBox" BasedOn="{StaticResource {x:Type CheckBox}}">
        <Setter Property="MinWidth" Value="75" />
    </Style>
</WrapPanel.Resources>

但是,我不想硬编码一个特定的宽度,而是让最大的 CheckBox 设置宽度(如果任何宽度 > 75,上面的方法也会失败)。

Slider 是独立的,应该允许大于 CheckBoxes。

我不想使用网格(带有 IsSharedSizeScope),因为我不想要硬编码的列数。

This article 提出了一个有趣的解决方案,但如果不创建自定义控件或使用 C# 代码来解决该问题会很好。

最好的方法是什么,最好只在 XAML 中?

【问题讨论】:

  • 我删除了我的答案,因为我认为你的意思是没有网格,如果我写它的第一种方式更适合你,那么让我知道,我可以取消编辑它。
  • 在这种情况下,我对 Grid 的唯一看法是我不想要硬编码的列数,因此您的解决方案效果很好。您最初的解决方案也不错,重复性更高,但也更直接。

标签: wpf xaml layout itemscontrol wrappanel


【解决方案1】:

我最初使用 IsSharedSizeGroup 进行了研究,但遇到了障碍,使其动态应用于事物而不是显式包装项目。在这种情况下,从长远来看,在代码或其他基于代码的解决方案中创建 AttachedProperty 可能比仅使用 XAML 的方法更好。但是,要创建纯粹的 XAML 解决方案,我们可以使用 ColumnDefinition 上的 SharedSizeGroup 属性来共享每个元素的大小,然后使用设置 WrapPanel 上的 IsSharedSizeScope 属性。这样做将使 WrapPanel 中具有相同 SharedSizeGroup 的所有内容共享其列的宽度和行的高度。要包装当前不在 XAML 中但将被添加到 WrapPanel 的 ComboBox 和可能的 ComboBox,我们可以创建一个 Style 并重新模板化 ComboBox 以用 Grid 基本包装它。

<WrapPanel Grid.IsSharedSizeScope="True">
  <WrapPanel.Resources>
    <Style TargetType="{x:Type CheckBox}">
      <Setter Property="Template">
        <Setter.Value>
          <ControlTemplate TargetType="{x:Type CheckBox}">
            <Grid Background="LightBlue">
              <Grid.ColumnDefinitions>
                <ColumnDefinition SharedSizeGroup="WrapPannelGroup" />
              </Grid.ColumnDefinitions>
              <CheckBox Style="{x:Null}"
                        IsChecked="{TemplateBinding IsChecked}">
                <!--Other TemplateBindings-->
                <CheckBox.Content>
                  <ContentPresenter />
                </CheckBox.Content>
              </CheckBox>
            </Grid>
          </ControlTemplate>
        </Setter.Value>
      </Setter>
    </Style>

  </WrapPanel.Resources>
  <CheckBox>Really long name</CheckBox>
  <CheckBox>Short</CheckBox>
  <CheckBox IsChecked="True">Longer again</CheckBox>
  <CheckBox>Foo</CheckBox>
  <Slider MinWidth="200" />
</WrapPanel>

在这里,我们将 WrapPannel 内没有样式的所有 CheckBox 重新模板化为由 Grid 包围的 CheckBox。然而,正因为如此,我们需要重新绑定我们想要维护的所有 CheckBoxes 属性。虽然这可能会变得繁重,但它也允许使用纯 XAML 方法。

【讨论】:

    【解决方案2】:

    您可以添加执行所需工作的属性或转换器,然后将每列的宽度绑定到它。属性或转换器可以访问整个项目列表,找到最宽的项目,并返回所有元素所需的宽度。

    【讨论】:

      【解决方案3】:

      最好的方法是使用您发布的文章中的 CustomControl。

      您遇到的任何解决方案都必须遍历项目列表并在测量阶段找到最大宽度。

      必须提供任何类型的仅 XAML 答案 OOTB(例如 IsSharedSizeScope),或者将利用某种多重绑定将项目链接在一起。因此,任何类型的 XAML 答案都会充满标记,这使得它更加冗长(并且不那么优雅)。

      我看到的对您发布的 CodeProject 文章的唯一修改是添加了“关闭”对某些元素(如滑块)的考虑的功能。这可以作为附加属性来完成。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-06-29
        • 2011-08-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多