Puzzle - Dynamically change data template control from another data template
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"/>
</B开发者_如何学JAVAorder>
</DataTemplate>
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.
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.
精彩评论