Синхронизация ширины элементов управления WPF в WrapPanel - PullRequest
3 голосов
/ 24 июня 2009

У меня есть этот случай

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

Я хочу, чтобы все флажки внутри WrapPanel были одинаковой ширины.

Добавление следующего почти достигает желаемого эффекта

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

Однако я не хочу жестко задавать конкретную ширину, а позволить самому большому CheckBox задавать ширину (вышеприведенное также не работает, если есть ширина> 75).

Ползунок независим и должен быть больше, чем CheckBoxes.

Я не хочу использовать Grid (с IsSharedSizeScope), поскольку мне не нужно жестко закодированное количество столбцов.

В этой статье представлено интересное решение, но было бы неплохо решить проблему без создания пользовательского элемента управления или использования кода C #.

Каков наилучший способ сделать это, предпочтительно только в XAML?

Ответы [ 3 ]

8 голосов
/ 24 июня 2009

Первоначально я смотрел на это с помощью IsSharedSizeGroup, но наткнулся на препятствие, сделав его динамически применимым к вещам вместо явной упаковки элементов. В этом случае создание AttachedProperty в коде или другом решении, основанном на коде, в конечном итоге может оказаться лучше, чем подход, основанный только на XAML. Однако для создания чисто XAML-решения мы можем использовать свойство SharedSizeGroup в ColumnDefinition для совместного использования размеров каждого элемента, а затем использовать свойство IsSharedSizeScope в WrapPanel. В результате все содержимое в WrapPanel с одной и той же SharedSizeGroup будет иметь общую ширину для столбцов и высоту для строк. Чтобы обернуть ComboBox и, возможно, ComboBox, которые в данный момент отсутствуют в XAML, но будут добавлены в WrapPanel, мы можем создать стиль и повторно создать шаблон 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>

Здесь мы повторно шаблонируем все CheckBox-ы без стиля внутри WrapPannel, чтобы вместо этого быть CheckBoxes, окруженными Grid. Однако из-за этого нам нужно повторно связать все свойства CheckBoxes, которые мы хотим сохранить. Хотя это может стать обременительным, оно также допускает чистый подход XAML.

1 голос
/ 24 июня 2009

Вы можете добавить свойство или конвертер, который выполняет необходимую работу, а затем привязать к нему ширину каждого столбца. Свойство или конвертер могут получить доступ ко всему списку элементов, найти самый широкий и вернуть нужную ширину для всех элементов.

0 голосов
/ 24 июня 2009

Лучший способ сделать это - использовать CustomControl как статью, которую вы опубликовали.

Любое решение, с которым вы столкнетесь, будет вынуждено перебирать список элементов и находить максимальную ширину на этапе измерения.

Любой вид ответа только на XAML должен быть предоставлен OOTB (например, IsSharedSizeScope) или использовать некий вид мультисвязывания для связи элементов. Таким образом, любой ответ XAML будет полон разметки, что делает его более многословным (и менее элегантным).

Единственное изменение, которое я вижу в опубликованной вами статье CodeProject, - это добавление возможности «отключать» рассмотрение определенных элементов (например, вашего слайдера). Это можно сделать как дополнительное прикрепленное свойство.

...