views:

104

answers:

2

I have a DataTemplate that contains an Expander with a border in the header. I want the header border to have round corners when collapsed and straight bottom corners when expanded. What would best practice be for achieving this (bonus points for code samples as I am new to XAML)?

This is the template that holds the expander:

    <DataTemplate x:Key="A">
        <StackPanel>
            <Expander Name="ProjectExpander" Header="{Binding .}" HeaderTemplate="{StaticResource B}" >
                <StackPanel>
                    <Border CornerRadius="0,0,2,2">

This is the expander datatemplate:

    <DataTemplate x:Key="B">
        <Border x:Name="ProjectExpanderHeader"
                CornerRadius="{Binding local:ItemUserControl.ProjectHeaderBorderRadius, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContentPresenter}}}"
                Background="{StaticResource ItemGradient}"   
                HorizontalAlignment="{Binding HorizontalAlignment,
                                              RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContentPresenter}},
                                              Mode=OneWayToSource}">
            <local:ItemContentsUserControl Height="30"/>
        </Border>
    </DataTemplate>
+1  A: 

Bind the CornerRadius property to the Expander.IsExpanded property and attach an IValueConverter that returns rounded corners when false and straight bottom corners when true. It's not the most elegant, but it will get the job done.

The other way to do this, if using MVVM, would be to expose a boolean property and bind it to the Expander.IsExpanded property. Then expose another property for the CornerRadius, which checks the boolean property and returns the appropriate values. This is definitely the "best practice" way to go about this.

Charlie
+1  A: 

Another way to do this is by editing the control template. The argument can be made that this is the best practice, though I'm not sure I'm ready to commit to that.

It's straightforward to do this if you have Expression Blend. An advantage of editing the control template is that it separates the behavior of the Expander from your data template, so that you can reuse it across different types of data. A disadvantage is that you end up embedding the properties of the header's Border in the control template, so you can't really change them for any individual instance of the control. (Other disadvantages: you have to have Expression Blend, and it produces a big bolus of XAML that you have to put in your resource dictionary.)

In Expression Blend, create an empty page and put an Expander on it. Right-click on the Expander and pick "Edit Template/Edit a Copy...". Give it a name like "ExpanderRoundedCorners".

This will add about 200 lines of XAML to Page.Resources, but most of this is used to create the graphics on the expand button. Switch to XAML view and search for the ToggleButton named "HeaderSite". This is the expand button. Note that its Content property is set to {TemplateBinding Header}. We'll want to fix that.

Delete the Content property, and add a child element to the ToggleButton like this:

<ToggleButton.Content>
  <Border x:Name="HeaderBorder" BorderBrush="Red" BorderThickness="2">
    <ContentPresenter Content="{TemplateBinding Header}"/>
 </Border>
</ToggleButton.Content>

Now find the trigger that makes ExpandSite visible when the ToggleButton is pressed. Add this setter to it:

<Setter TargetName="HeaderBorder" Property="CornerRadius" Value="4"/>

That's it. Now every time you create an Expander with the ExpanderRoundedCorners style, the header content will be enclosed in a Border whose corners are rounded when the Expander is expanded.

You'll probably want to jigger around with this a little more when you've got it working. At the least, you'll want to remove the Border from the header template in your style, since it's now part of the control template.

Robert Rossney