Связывание цвета кисти со свойствами в ControlTemplate - PullRequest
2 голосов
/ 01 декабря 2010

Я пытаюсь создать CustomControl, производный от Button, который просто отображается в виде цветного прямоугольника. Я хочу, чтобы на моем элементе управления было два свойства, которые можно установить, которые задают обычный цвет (ColdColor), и другой цвет, который будет использоваться, когда мышь находится над элементом управления (HotColor).

Я не могу понять, как настроить привязку между цветом кисти и свойствами элемента управления. Это мой код:

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.TargetProperty="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()));
}

Использование в MainWindow.xaml:

<my:TestCustomControl ColdColor="#FF0000AF" HotColor="#FFFF00AF"/>

РЕДАКТИРОВАТЬ: Сказать, что «не работает» означает, что TestCustomControl является полностью прозрачным.

Ответы [ 2 ]

3 голосов
/ 01 декабря 2010

Нет очевидной проблемы (afaik), я бы изменил этот кусок кода:

UIPropertyMetadata(new Color())

до

UIPropertyMetadata(Colors.White)

и посмотрите, не в этом ли проблема с 'новым цветом ()'

РЕДАКТИРОВАТЬ -

если вышеописанное не сработало, попробуйте изменить это

<SolidColorBrush Color="{TemplateBinding ColdColor}" />

к этому

<SolidColorBrush Color="{Binding 
    RelativeSource={RelativeSource TemplatedParent}, 
    Path=ColdColor}" />
0 голосов
/ 15 сентября 2013

Диспетчер визуальных состояний имеет связанное ограничение: он не может анимировать свойства, заданные с помощью привязки.Таким образом, вы просто пытаетесь сделать что-то, что не может быть сделано.

Что вы можете сделать, так это продублировать элементы и использовать непрозрачность для перехода.Ниже показано, как вы будете делать это с VSM и с непрозрачностями:

При наличии пользовательского элемента управления TwoColorBox со свойствами зависимостей

 Color ColorOne
 Color ColorTwo

и с визуальными состояниями:

 ColorOne
 ColorTwo

Следующий шаблон управления будет работать так, как вы хотите, без просвечивания прозрачности

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