Posted by: Zeeshan Amjad | July 11, 2012

Up sided ComboBox


I came across an interesting question that how can we make a combo box that popup up side rather than traditional down side. Like most of the WPF problem this problem can be solved in more than one way. Two approaches that quickly came to my mind is either doing it via code or via XAML.

Both approaches have some trade off. At first attempt it looks like that we have to change the control template of the combo box. But unlike style we can’t define a portion of control template that is based on some other control template. We have to define the whole control template.

Fortunately the control template of combo box defined some predefine control template and as with WPF naming convention they start with PART_. We already saw one example of PART_ control template of progress bar here. ComboBox uses two predefined control templates named PART_Popup and PART_EditableTextBox. Here we are going to modify the first one i.e. PART_Popup.

The first way to modify PART_Popup control template is using code. Here is a simple code to modify the template and set the Popup placement at top. We can even set the placement to any other place like right, left etc.

Code Snippet
ControlTemplate ct = combo.Template;

Popup popup = ct.FindName("PART_Popup", combo) as Popup;

if (popup != null)
{
    popup.Placement = PlacementMode.Top;
}

 

Be sure to call this code from window loaded event handler not from the constructor of the window. Although there is less code in this approach, but we have to do the same thing with all the instance of the combo box. The alternate would be to create a child class from ComboBox class write this code there and use that class everywhere we need a ComboBox with upside popup.

The other approach is to do the same thing with control template. In that approach we have to define the complete control template that is almost similar to existing template except this small change. We have to write lots of code (XAML) in this approach, but we don’t have to create a new child class from ComboBox class. And whenever we need a combo box with upside popup we just apply that control template there.

Here is a complete code of your control template with up side popup for combo box.

Code Snippet
<Window x:Class="WpfCombo.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&quot;
        Title="Upside ComboBox" Height="300" Width="400">
    <Window.Resources>
        <Style TargetType="{x:Type ComboBox}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="ComboBox">
                        <Grid>
                            <ToggleButton x:Name="DropDownToggle"
                              HorizontalAlignment="Stretch" VerticalAlignment="Stretch"  
                              Margin="-1" HorizontalContentAlignment="Right"
                              IsChecked="{Binding Path=IsDropDownOpen,Mode=TwoWay,
                                          RelativeSource={RelativeSource TemplatedParent}}">
                                <Path x:Name="BtnArrow" Height="4" Width="8"
                                    Stretch="Uniform" Margin="0,0,6,0" Fill="Black"
                                    Data="F1 M 300,-190L 310,-190L 305,-183L 301,-190 Z " />
                                                        </ToggleButton>
                            <ContentPresenter x:Name="ContentPresenter" Margin="6,2,25,2"
                              Content="{TemplateBinding SelectionBoxItem}"
                              ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}"
                              ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}">
                            </ContentPresenter>
                            <TextBox x:Name="PART_EditableTextBox"
                                  Style="{x:Null}"
                                  Focusable="False"
                                  Background="{TemplateBinding Background}"
                                  HorizontalAlignment="Left"
                                  VerticalAlignment="Center"
                                  Margin="3,3,23,3"
                                  Visibility="Hidden"
                                  IsReadOnly="{TemplateBinding IsReadOnly}"/>                            
                            <Popup x:Name="PART_Popup" Placement="Top"
                                      IsOpen="{TemplateBinding IsDropDownOpen}">
                                <Border x:Name="PopupBorder"
                                        HorizontalAlignment="Stretch" Height="Auto"                                                                         
                                        MinWidth="{TemplateBinding ActualWidth}"
                                        MaxHeight="{TemplateBinding MaxDropDownHeight}"
                                        BorderThickness="{TemplateBinding BorderThickness}"
                                        BorderBrush="Black" Background="White" CornerRadius="3">
                                    <ScrollViewer x:Name="ScrollViewer" BorderThickness="0" Padding="1">
                                        <ItemsPresenter/>
                                    </ScrollViewer>
                                </Border>
                            </Popup>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Resources>
    <Grid>
        <ComboBox Height="30" Margin="5">
            <ComboBoxItem>California</ComboBoxItem>
            <ComboBoxItem>Maryland</ComboBoxItem>
            <ComboBoxItem>Texas</ComboBoxItem>
            <ComboBoxItem>Washington</ComboBoxItem>
        </ComboBox>
    </Grid>
</Window>

 

Here is the output of this program.

UpSideComboBox

Advertisements

Responses

  1. Dear,
    I would like to know what is combo in the code combo.Template please.

    • Thanks for pointing out this. It is the name of the ComboBox defined in XAML.

      Regards
      Zeeshan Amjad

  2. […] already saw an example of using PART_ template here and here. Now the question is if we want to use PART_ in our control then how can we do […]


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Categories

%d bloggers like this: