ControlTemplate с привязкой VisualState ColorAnimation к прикрепленному свойству

У меня есть присоединенное свойство, которое я хотел бы связать с моей кнопкой ControlTemplate VisualStateManager.

Ниже приведен код свойства и XAML для стиля кнопки. У меня нет ошибок или предупреждений, но кнопка не меняет цвет, когда я навожу на нее мышь или когда я ее нажимаю.

Что не так с этим? Я просмотрел следующие примеры, и они пока не работают:

Как использовать свойство Attached в стиле?

Проблема чтения AttachedProperty в ControlTemplate

Вот свойство:

using System.Windows;
using System.Windows.Media;

namespace company.project.Utilities.AttachedBehaviors
{
    public class Attached : DependencyObject
    {
        // Attached properties...
        #region MouseOverColor Property

        public static readonly DependencyProperty MouseOverColorProperty = DependencyProperty.RegisterAttached(
              "MouseOverColor",
              typeof(Color),
              typeof(Attached)
            );

        public static void SetMouseOverColor(UIElement element, Color value)
        {
            element.SetValue(MouseOverColorProperty, value);
        }

        public static Color GetMouseOverColor(UIElement element)
        {
            return (Color)element.GetValue(MouseOverColorProperty);
        }

        #endregion

        #region PressedColor Property

        public static readonly DependencyProperty PressedColorProperty = DependencyProperty.RegisterAttached(
              "PressedColor",
              typeof(Color),
              typeof(Attached)
            );

        public static void SetPressedColor(UIElement element, Color value)
        {
            element.SetValue(PressedColorProperty, value);
        }

        public static Color GetPressedColor(UIElement element)
        {
            return (Color)element.GetValue(PressedColorProperty);
        }

        #endregion
    }
}

Вот стиль:

xmlns:attached="clr-namespace:company.project.Utilities.AttachedBehaviors;assembly=company.project.Utilities"

<Style x:Key="DialogButtonStyle" TargetType="{x:Type Button}" BasedOn="{StaticResource StandardButtonStyle}">
    <Setter Property="Background" Value="{StaticResource ElectroTekGrayBrush}" />
    <Setter Property="attached:Attached.MouseOverColor" Value="{StaticResource ElectroTekGreen}" />
    <Setter Property="attached:Attached.PressedColor" Value="{StaticResource ElectroTekLightGray}" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Button}">
                <Grid>
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup x:Name="CommonStates">
                            <VisualState x:Name="Normal" />
                            <VisualState x:Name="MouseOver">
                                <Storyboard>
                                    <ColorAnimation Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)" Storyboard.TargetName="Border" To="{Binding Path=(attached:Attached.MouseOverColor), RelativeSource={RelativeSource AncestorType=Button}}" Duration="0" />
                                </Storyboard>
                            </VisualState>
                            <VisualState x:Name="Pressed">
                                <Storyboard>
                                    <ColorAnimation Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)" Storyboard.TargetName="Border" To="{Binding Path=(attached:Attached.PressedColor), RelativeSource={RelativeSource AncestorType=Button}}" Duration="0" />
                                </Storyboard>
                            </VisualState>
                            <VisualState x:Name="Disabled" />
                        </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>
                    <Border Name="Border" Background="{TemplateBinding Background}" CornerRadius="{Binding RelativeSource={RelativeSource Self}, Path=ActualHeight, Converter={StaticResource MathConverter}, ConverterParameter=(@VALUE/2)}" IsHitTestVisible="True">
                        <Grid>
                            <TextBlock x:Name="TextBlock" Text="{TemplateBinding Content}" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="White" FontSize="15" />
                        </Grid>
                    </Border>
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter TargetName="TextBlock" Property="Cursor" Value="Hand" />
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Вот кнопка:

<Button Style="{StaticResource DialogButton}" />

person Matt Becker    schedule 17.10.2014    source источник
comment
Боюсь, вы не можете использовать Binding для To или From для Storyboard. Также странно, что в этом случае нет никакой ошибки.   -  person King King    schedule 17.10.2014
comment
Ладно, переходим на триггеры.   -  person Matt Becker    schedule 17.10.2014


Ответы (1)


Хорошо, я предположил, что @King King был прав в отношении свойств To и From и просто реализовал ту же функциональность с помощью триггеров. Вот стиль, если кому надо.

<Style x:Key="DialogButtonStyle" TargetType="{x:Type Button}" BasedOn="{StaticResource StandardButtonStyle}">
    <Setter Property="Background" Value="{StaticResource ElectroTekGrayBrush}" />
    <Setter Property="attached:Attached.MouseOverColor" Value="{StaticResource ElectroTekGreen}" />
    <Setter Property="attached:Attached.PressedColor" Value="{StaticResource ElectroTekOrange}" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Button}">
                <Grid>
                    <Border Name="border" Background="{TemplateBinding Background}" CornerRadius="{Binding RelativeSource={RelativeSource Self}, Path=ActualHeight, Converter={StaticResource MathConverter}, ConverterParameter=(@VALUE/2)}" IsHitTestVisible="True" Cursor="Hand">
                        <TextBlock x:Name="TextBlock" Text="{TemplateBinding Content}" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="White" FontSize="15" Cursor="Hand" />
                    </Border>
                </Grid>
                <ControlTemplate.Resources>
                    <SolidColorBrush x:Key="MouseOverBrush" Color="{Binding Path=(attached:Attached.MouseOverColor), RelativeSource={RelativeSource AncestorType=Button}}" />
                    <SolidColorBrush x:Key="PressedBrush" Color="{Binding Path=(attached:Attached.PressedColor), RelativeSource={RelativeSource AncestorType=Button}}" />
                </ControlTemplate.Resources>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver" Value="True" SourceName="border">
                        <Setter Property="Background" Value="{StaticResource MouseOverBrush}" TargetName="border" />
                    </Trigger>
                    <Trigger Property="IsPressed" Value="True">
                        <Setter Property="Background" Value="{StaticResource PressedBrush}" TargetName="border" />
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
person Matt Becker    schedule 17.10.2014
comment
Это хорошо, если вы не используете раскадровку для реальных анимаций, т.е. е. установите Duration на 0. Мне нужно это с анимацией, поэтому я не могу использовать триггеры в моем случае. Я где-то читал, что анимация должна быть заморожена и поэтому не может использовать привязки. - person ygoe; 18.06.2016