开发者

Binding brush color to properties in ControlTemplate

开发者 https://www.devze.com 2023-01-27 23:39 出处:网络
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 (Col

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>
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号