2011-01-19 5 views
2

Я размышляю о том, как WPF ComboBox показывает пустое значение, как будто ничего не выбрано, если для IsEnabled установлено значение false. Как всегда, я пытаюсь сделать это, не пересматривая весь шаблон управления для ComboBox, который всегда является борьбой с WPF. Если у кого-то есть решения, более элегантные, чем переопределение всего шаблона управления ComboBox, пожалуйста, дайте мне знать.WPF ComboBox, который ничего не отображает при отключении (IsEnabled == false)

Причина в том, что я пытаюсь сделать, так это то, что у меня есть CheckBox, который представляет собой опцию «Все», и когда этот флажок установлен, он отключает ComboBox, который используется для выбора только одного отдельного элемента. Если мой CheckBox проверен, иногда пользователи сбивают с толку, чтобы увидеть значение, оставшееся в ComboBox, поскольку это значение не имеет смысла в этом состоянии пользовательского интерфейса.

Другим требованием является то, что решение не может изменить SelectedValue, SelectedIndex или SelectedItem значения ComboBox, так как я хотел бы сохранить previuosly выбранный элемент в том случае, когда пользователи неустановленными «Все» CheckBox.

Решение на основе ответа HCL в:

<ComboBox IsEnabled="{Binding ElementName=myCheckBox, Path=IsChecked}" 
      ItemsSource="{Binding Path=MyItems}" 
      SelectedValue="{Binding Path=MySelectedItem}"> 
    <ComboBox.ItemTemplate> 
     <DataTemplate> 
      <ContentControl x:Name="content" Content="{Binding MyItemDescription}" /> 
      <DataTemplate.Triggers> 
       <DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=ComboBox}, Path=IsEnabled}" 
          Value="False"> 
        <Setter TargetName="content" 
          Property="Visibility" 
          Value="Hidden" /> 
       </DataTrigger> 
      </DataTemplate.Triggers> 
     </DataTemplate> 
    </ComboBox.ItemTemplate> 
</ComboBox> 

ответ

1

Вы можете сделать что-то с триггерами:

Попробуйте установить ItemTemplate в пустой DataTemplate, когда коробка выключена. Это повлияет на рендеринг выбранного элемента и, следовательно, скрыть его.
Другим простым, но не очень приятным решением было бы установить цвет переднего плана так же, как и цвет фона.

0

Я считаю, что вы можете сделать это со стилем, а не переопределять шаблон управления. Используйте Trigger в свойстве IsEnabled, чтобы установить текст, показанный в ComboBox. Изменение метода SelectedItem будет моим первым подходом, но поскольку вы не хотите этого делать, вы можете найти успех DisplayMemberPath. Что-то вроде этого (непроверено) ...

<Style TargetType="{x:Type ComboBox}"> 
    <Style.Triggers> 
     <Trigger Property="IsEnabled" Value="False"> 
      <Trigger.Setters> 
       <Setter Property="DisplayMemberPath" Value="{x:Null}"/> 
      </Trigger.Setters> 
     </Trigger> 
    </Style.Triggers> 
</Style> 
+0

К сожалению, это не сработало в моих тестах, хотя возможно, что у меня что-то не так. Мне понравилась простота больше, чем указание ItemTemplate. – jpierson

+0

В попытке выяснить, действительно ли этот метод возможен, я наткнулся на этот пост на форумах MSDN, который кажется довольно интересным. http://social.msdn.microsoft.com/Forums/en/wpf/thread/4c359378-ba98-42a1-a468-0f18f5626fcc – jpierson

0

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

<ComboBox.Style> 
     <Style TargetType="ComboBox"> 
     <Setter Property="Template"> 
      <Setter.Value> 
      <ControlTemplate TargetType="ComboBox"> 
       <DockPanel> 
       <CheckBox x:Name="IsActive" DockPanel.Dock="Left"/> 
       <Grid> 
        <ComboBox 
        ItemsSource="{TemplateBinding ItemsSource}" 
        SelectedItem="{TemplateBinding SelectedItem}" 
        SelectedIndex="{TemplateBinding SelectedIndex}" 
        SelectedValue="{TemplateBinding SelectedValue}"> 
        <ComboBox.Style> 
         <Style TargetType="ComboBox"> 
         <Setter Property="Visibility" Value="Visible"/> 
         <Style.Triggers> 
          <DataTrigger Binding="{Binding ElementName=IsActive, Path=IsChecked}" Value="False"> 
          <Setter Property="Visibility" Value="Collapsed"/> 
          </DataTrigger> 
         </Style.Triggers> 
         </Style> 
        </ComboBox.Style> 
        </ComboBox> 
        <ComboBox> 
        <ComboBox.Style> 
         <Style TargetType="ComboBox"> 
         <Setter Property="Visibility" Value="Collapsed"/> 
         <Style.Triggers> 
          <DataTrigger Binding="{Binding ElementName=IsActive, Path=IsChecked}" Value="False"> 
          <Setter Property="Visibility" Value="Visible"/> 
          </DataTrigger> 
         </Style.Triggers> 
         </Style> 
        </ComboBox.Style>      
        </ComboBox> 
       </Grid> 
       </DockPanel> 
      </ControlTemplate> 
      </Setter.Value> 
     </Setter> 
     </Style> 
    </ComboBox.Style> 

Это сохраняет выбранный элемент, выбранный индекс и выбранное значение так же, как вы хотите. На самом деле, он делает это слишком хорошо; на самом деле нет способа сказать, что пользователь деактивировал поле со списком, поскольку на ComboBox нет свойства, которое предоставляет эту информацию. Я бы на самом деле реализовал это как пользовательский элемент управления, полученный из ComboBox, который выставил значение этого поля как свойство IsActive. Есть много других способов сделать это.

+0

Идеальная идея, хотя решение, предложенное HCL, и которое я подробно рассмотрел в обновлении моего вопроса, является все еще намного более короткий код, чем этот, и достигает того же результата.Мне любопытно, есть ли какие-либо другие преимущества для вашей техники или его стихотворений. В любом случае, спасибо за ваш ответ. – jpierson

+1

Моя техника позволяет вам менять внешний вид, если поле со списком неактивно, но это действительно единственное преимущество, которое я могу придумать в этом конкретном случае. –