views:

540

answers:

4

I want to display a custom template/item as selected item in ComboBox (this item does not actually exist in the list of items and is updated differently). This does not even needs to be an item, just providing a custom view would work.

How can I do this while staying within current ComboBox theme (so no ControlTemplate replacement possible)? As far as I see, all of SelectionBox* properties are not editable and internally ComboBox uses unnamed ContentPresenter.

A: 

You need to look into Triggers and Styles. You might also want to look into some of my older questions here on StackOverflow that helped me conquer these problems:

Filip Ekberg
Thanks, unfortunately that was kind of too abstract as compared to other answers. I have a general idea of how triggers work, it was the {x:Null} solution I couldn't invent.
Andrey Shchekin
A: 

If I have this straight, you want a control that has something arbitrary displayed along with a drop-down button that displays a list of items with checkboxes next to them?

I wouldn't even bother trying to restyle a ComboBox to achieve this. The problem is that ComboBox is more specialized down a different path than what you need. If you look at the ComboBox ControlTemplate Example, you'll see that it simply uses a Popup control to display the list of possible values.

You can take pieces of that template as guidance to creating a UserControl that is easier to understand and better provides what you want. You'll even be able to add a SelectedItems property and such that ComboBox doesn't provide.

An example of what I mean by guidance: the Popup has an IsOpen property. In the control template, it's set to {TemplateBinding IsDropDownOpen}, which means that the ComboBox class has an IsDropDownOpen property that is changed in order to control the expand/collapse of the Popup.

Joel B Fant
The problem with custom controls are that they are not styled by built-in styles. I have already build a custom control with SelectedItems, but inside it relies on a ComboBox since I want default styles to work with it without repeating them.
Andrey Shchekin
+1  A: 

Check this : http://stackoverflow.com/questions/1466592/displaying-the-selected-item-differently-in-combobox

David Brunelle
Looks great (DataTrigger/{x:Null}), I will check this later today.
Andrey Shchekin
This is the solution, thanks. Unfortunately I can not approve two answers and Ray Burns provided more detailed (and more specific) solution, so I'll approve his and upvote yours.
Andrey Shchekin
Meh... only 3 reps from being able to retag questions :D
David Brunelle
+1  A: 

I would do it like this:

<Window.Resources>

  <DataTemplate x:Key="NormalItemTemplate" ...>
    ...
  </DataTemplate>

  <DataTemplate x:Key="SelectionBoxTemplate" ...>
    ...
  </DataTemplate>

  <DataTemplate x:Key="CombinedTemplate">
    <ContentPresenter x:Name="Presenter"
       Content="{Binding}"
       Template="{StaticResource NormalItemTemplate}" />
    <DataTemplate.Triggers>
      <DataTrigger
        Binding="{Binding RelativeSource={RelativeSource FindAncestor,ComboBoxItem,1}}"
        Value="{x:Null}">
        <Setter TargetName="Presenter" Property="Template"
                Value="{StaticResource SelectionBoxTemplate}" />
      </DataTrigger>
    </DataTemplate.Triggers>
  </DataTemplate>

</Window.Resources>

...

<ComboBox
  ItemTemplate="{StaticResource CombinedTemplate}"
  ItemsSource="..."
  ... />

The reason this works is that CombinedTemplate normally just uses NormalItemTemplate to present its data, but if there is no ComboBoxItem ancestor it assumes it is in the selection box so it uses SelectionBoxTemplate.

Note that the three DataTemplates could be included in any level of ResourceDictionary (not just at the Window level) or even directly within the ComboBox, depending on your preference.

Ray Burns
Thanks, I'll definitely try this one.
Andrey Shchekin
It is both an elegant *and* working solution, thanks a lot!
Andrey Shchekin