如何为边框控件创建闪烁和普通背景视觉状态

时间:2013-06-04 12:28:41

标签: .net wpf border visualstatemanager visualstates

如何为WPF Border控件创建2个可视状态Transparent和{{1}之间闪烁背景颜色的 }};和一个普通的,将边框背景颜色设置回Red并停止闪烁?

注意: WPF Transparent控件用于另一个控件的Border内。

我还要求当某个属性说ContentTemplate IsEnabledBorder更改为False时,会触发它们,反之亦然;并且IsEnabled属性绑定到ViewModel属性。当我们点击边框时,闪烁应该停止,背景应该恢复正常..

2 个答案:

答案 0 :(得分:1)

您可以使用VisualStateManager定义VisualStates。要在边框上获得您想要的行为,以下应该是一个很好的起点:

xaml:

  <Border Name="TheBorder" BorderThickness="5"
            Margin="30" Padding="20"
            wpfApplication1:StateManager.VisualState="{Binding ElementName=TheBorder,
                                                               Path=IsEnabled, Mode=TwoWay,
                                                               Converter={StaticResource EnabledToVisualStateConverter}}">
        <Border.Background>
            <SolidColorBrush x:Name="BackgroundBrush" Color="Transparent"/>
        </Border.Background>
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup Name="Common">
                <VisualState x:Name="Normal"/>
                <VisualState x:Name="Flash">
                    <Storyboard>
                        <ColorAnimation Storyboard.TargetName="BackgroundBrush" 
                                        Storyboard.TargetProperty="Color" To="Red"
                                        RepeatBehavior="Forever"/>
                    </Storyboard>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>
    </Border>

转换器:

    public class EnabledToVisualStateConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var isEnabled = (bool) value;
        if (isEnabled)
            return "Flash";

        return "Normal";
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

用于更改VisualState的StateManager类:

    public class StateManager
{
    private static string _valueToApplyOnInitialization;

    public static readonly DependencyProperty VisualStateProperty =
        DependencyProperty.RegisterAttached("VisualState", typeof (string), typeof (StateManager),
                                            new PropertyMetadata(VisualStateChangeCallback));

    public static string GetVisualState(DependencyObject obj)
    {
        return (string)obj.GetValue(VisualStateProperty);
    }
    public static void SetVisualState(DependencyObject obj, string value)
    {
        obj.SetValue(VisualStateProperty, value);
    }

    public static void VisualStateChangeCallback(object sender, DependencyPropertyChangedEventArgs args)
    {
        var element = sender as FrameworkElement;
        if (element == null)
            return;

        if (!element.IsInitialized)
        {
            _valueToApplyOnInitialization = (String) args.NewValue;
            element.Initialized += OnElementInitialized;
        }
        else
            VisualStateManager.GoToElementState(element, (string)args.NewValue, true);
    }

    private static void OnElementInitialized(object sender, EventArgs e)
    {
        var element = sender as FrameworkElement;
        if (element == null)
            return;

        VisualStateManager.GoToElementState(element, _valueToApplyOnInitialization, true);
        element.Initialized -= OnElementInitialized;
    }
}

如果您想使用ViewModel中的属性而不是Border上的IsEnabled属性,那么只需将View绑定替换为带有ViewModel属性的'TheBorder'。

答案 1 :(得分:1)

如果你想纯粹在xaml中执行动画,那么你可以使用Triggers而不是VisualStateManager。以下内容应该为您提供您所追求的行为:

 <Border Name="TheBorder" BorderThickness="5"
            Margin="30" Padding="20" >
        <Border.Background>
            <SolidColorBrush x:Name="BackgroundBrush" Color="Transparent" />
        </Border.Background>
        <Border.Style>
            <Style TargetType="{x:Type Border}">
                <Style.Triggers>
                    <Trigger Property="IsEnabled" Value="True">
                        <Trigger.EnterActions>
                            <BeginStoryboard Name="FlashStoryboard">
                                <Storyboard>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background"
                                                                   Duration="0:0:1" RepeatBehavior="Forever">
                                        <ObjectAnimationUsingKeyFrames.KeyFrames>
                                            <DiscreteObjectKeyFrame KeyTime="0:0:0.5">
                                                <DiscreteObjectKeyFrame.Value>
                                                    <SolidColorBrush Color="Red"/>
                                                </DiscreteObjectKeyFrame.Value>
                                            </DiscreteObjectKeyFrame>
                                        </ObjectAnimationUsingKeyFrames.KeyFrames>
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>
                            </BeginStoryboard>
                        </Trigger.EnterActions>
                        <Trigger.ExitActions>
                            <StopStoryboard BeginStoryboardName="FlashStoryboard"></StopStoryboard>
                        </Trigger.ExitActions>
                    </Trigger>
                </Style.Triggers>
            </Style>
        </Border.Style>
    </Border>