如何为WPF Border
控件创建2个可视状态:在Transparent
和{{1}之间闪烁背景颜色的 }};和一个普通的,将边框背景颜色设置回Red
并停止闪烁?
注意: WPF Transparent
控件用于另一个控件的Border
内。
我还要求当某个属性说ContentTemplate
IsEnabled
从Border
更改为False
时,会触发它们,反之亦然;并且IsEnabled属性绑定到ViewModel属性。当我们点击边框时,闪烁应该停止,背景应该恢复正常..
答案 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>