Binding brush color to properties in ControlTemplate
I am trying to make a CustomControl that derives from Button, which simply shows as a colored rectangle. I want to have two properties on my control that I can set, which specify the normal color (ColdColor), and another color that will be used when the mouse is over the control (HotColor).
I can't figure out how to get the binding set up between the brush color and the control properties. This is my code:
Generic.xaml:
<Style TargetType="{x:Type local:TestCustomControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:TestCustomControl}">
<Border BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Name="MyBorder">
<Border.Background>
<!-- This works: -->
<!--<SolidColorBrush Color="Green" />-->
<!-- This doesn't work: -->
<SolidColorBrush Color="{TemplateBinding ColdColor}" />
</Border.Background>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver">
<Storyboard>
<!-- This works: -->
<!--<ColorAnimation Storyboard.TargetProp开发者_JAVA百科erty="Background.Color" Storyboard.TargetName="MyBorder" To="Red" Duration="0:0:0.2"/>-->
<!-- This doesn't work: -->
<ColorAnimation Storyboard.TargetProperty="Background.Color" Storyboard.TargetName="MyBorder" To="{TemplateBinding HotColor}" Duration="0:0:0.2"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
TestCustomControl.cs:
public class TestCustomControl : Button
{
static TestCustomControl()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(TestCustomControl), new FrameworkPropertyMetadata(typeof(TestCustomControl)));
}
public Color HotColor
{
get { return (Color)GetValue(HotColorProperty); }
set { SetValue(HotColorProperty, value); }
}
// Using a DependencyProperty as the backing store for HotColor. This enables animation, styling, binding, etc...
public static readonly DependencyProperty HotColorProperty =
DependencyProperty.Register("HotColor", typeof(Color), typeof(TestCustomControl), new UIPropertyMetadata(new Color()));
public Color ColdColor
{
get { return (Color)GetValue(ColdColorProperty); }
set { SetValue(ColdColorProperty, value); }
}
// Using a DependencyProperty as the backing store for ColdColor. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ColdColorProperty =
DependencyProperty.Register("ColdColor", typeof(Color), typeof(TestCustomControl), new UIPropertyMetadata(new Color()));
}
Usage in MainWindow.xaml:
<my:TestCustomControl ColdColor="#FF0000AF" HotColor="#FFFF00AF"/>
EDIT: To say that "doesn't work" means that the TestCustomControl is entirely transparent.
There is no obvious problem (afaik), I would change this piece of code:
UIPropertyMetadata(new Color())
to
UIPropertyMetadata(Colors.White)
and see if its the 'new Color()' that's the problem
EDIT -
if the above didnt work, try changing this
<SolidColorBrush Color="{TemplateBinding ColdColor}" />
to this
<SolidColorBrush Color="{Binding
RelativeSource={RelativeSource TemplatedParent},
Path=ColdColor}" />
The visual state manager has a related limitation: it can not animate properties set with a binding. So you are just trying to do something that can't be done.
What you can do is duplicate the elements and use opacity to do the transition. The following shows how you would do this with the VSM and opacities:
Given a custom control TwoColorBox with dependency properties
Color ColorOne
Color ColorTwo
and with visual states:
ColorOne
ColorTwo
The following control template will do as you want without transparency bleed-through
<ControlTemplate TargetType="{x:Type view:TwoColorBox}">
<Grid Background="{TemplateBinding Background}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="ColorStates">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0:0:1"/>
</VisualStateGroup.Transitions>
<VisualState x:Name="ColorOne"/>
<VisualState x:Name="ColorTwo">
<Storyboard>
<DoubleAnimationUsingKeyFrames
Storyboard.TargetProperty="(UIElement.Opacity)"
Storyboard.TargetName="borderTwo">
<EasingDoubleKeyFrame KeyTime="0" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border
x:Name="borderOne"
BorderThickness="{TemplateBinding BorderThickness}">
<Border.BorderBrush>
<SolidColorBrush
Color="{Binding ColorOne, RelativeSource={RelativeSource TemplatedParent}}"/>
</Border.BorderBrush>
</Border>
<Border
x:Name="borderTwo"
BorderThickness="{TemplateBinding BorderThickness}" Opacity="0">
<Border.BorderBrush>
<SolidColorBrush
Color="{Binding ColorTwo, RelativeSource={RelativeSource TemplatedParent}}"/>
</Border.BorderBrush>
</Border>
</Grid>
</ControlTemplate>
精彩评论