在WrapPanel中同步WPF控件的宽度

4

我有这个案例

<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>

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

滑块是独立的,应该允许比复选框更大。

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

这篇文章提出了一个有趣的解决方案,但最好能够在不创建自定义控件或使用C#代码的情况下解决问题。

最佳方法是什么,最好只使用XAML?


我删掉了我的回答,因为我认为你的意思是没有网格,如果我最初写的方式对你更好,请告诉我,我可以撤销编辑。 - rmoore
我对于在这种情况下使用网格布局的唯一反感之处是我不想要一个硬编码的列数,所以你的解决方案非常好。你最初的解决方案也很好,有点重复但更加直接。 - Klas Mellbourn
3个回答

9
我最初使用IsSharedSizeGroup进行研究,但在使其动态应用于事物时遇到了障碍,而不是显式地包装项目。 在这种情况下,创建一个AttachedProperty或另一个基于代码的解决方案可能比仅使用XAML更好。 但是,为了创建纯XAML解决方案,我们可以利用ColumnDefinition上的SharedSizeGroup属性共享每个元素的大小,然后在WrapPanel上设置IsSharedSizeScope属性。 这样做将使WrapPanel中具有相同SharedSizeGroup的所有内容共享它们的列宽和行高。 要包装ComboBoxes并可能不在XAML中但将添加到WrapPanel中的ComboBoxes,我们可以创建一个Style并重新模板化ComboBox以基本包装它。
<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>

在这里,我们重新针对WrapPanel中没有样式的所有CheckBox进行模板重新设计,使其成为被Grid包围的CheckBox。但是,由于这个原因,我们需要重新绑定我们想要保持的所有CheckBox属性。虽然这可能会变得繁琐,但它也允许采用纯XAML方法。


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

0

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

无论您遇到什么解决方案,都必须在测量阶段遍历项目列表并查找最大宽度。

任何仅限于XAML的答案都必须作为OOTB(例如IsSharedSizeScope)提供,或者利用某种多绑定将项目链接在一起。因此,任何XAML答案都将充满标记,使其更冗长(而不够优雅)。

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接