我想给一个像行为一样的按钮,因为我想应用不对称的圆角边缘,摆脱标准按钮的焦点闪烁效果。我想在将鼠标悬停在它上面并点击它时应用不同的样式。除了两种样式之间的过渡之外,它的效果很好。考虑以下XAML
<local:ClickableBorder local:FrameworkElementExt.AttachIsPressed="True" CornerRadius="5,10,5,10" BorderThickness="1" Height="27.334" Margin="154.667,31.333,223.667,0" VerticalAlignment="Top">
<local:ClickableBorder.Style>
<Style TargetType="{x:Type local:ClickableBorder}">
<Setter Property="BorderBrush" Value="Black"/>
<Setter Property="Background" Value="LightGray"/>
<Style.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsMouseOver" Value="True"/>
<Condition Property="IsEnabled" Value="True"/>
</MultiTrigger.Conditions>
<MultiTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Duration="0:0:0.200" To="White" Storyboard.TargetProperty="BorderBrush.Color"/>
<ColorAnimation Duration="0:0:0.200" To="DarkGray" Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)"/>
</Storyboard>
</BeginStoryboard>
</MultiTrigger.EnterActions>
<MultiTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Duration="0:0:0.200" To="Black" Storyboard.TargetProperty="BorderBrush.Color"/>
<ColorAnimation Duration="0:0:0.200" To="LightGray" Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)"/>
</Storyboard>
</BeginStoryboard>
</MultiTrigger.ExitActions>
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="local:FrameworkElementExt.IsPressed" Value="True"/>
<Condition Property="IsEnabled" Value="True"/>
</MultiTrigger.Conditions>
<MultiTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Duration="0:0:0.200" To="DarkRed" Storyboard.TargetProperty="BorderBrush.Color"/>
<ColorAnimation Duration="0:0:0.200" To="Red" Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)"/>
</Storyboard>
</BeginStoryboard>
</MultiTrigger.EnterActions>
<MultiTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Duration="0:0:0.200" To="Black" Storyboard.TargetProperty="BorderBrush.Color"/>
<ColorAnimation Duration="0:0:0.200" To="LightGray" Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)"/>
</Storyboard>
</BeginStoryboard>
</MultiTrigger.ExitActions>
</MultiTrigger>
</Style.Triggers>
</Style>
</local:ClickableBorder.Style>
背后的相关代码
public class FrameworkElementExt
{
public static readonly DependencyProperty IsPressedProperty = DependencyProperty.RegisterAttached("IsPressed", typeof(bool), typeof(FrameworkElementExt), new PropertyMetadata(false));
public static readonly DependencyProperty AttachIsPressedProperty = DependencyProperty.RegisterAttached("AttachIsPressed", typeof(bool), typeof(FrameworkElementExt), new PropertyMetadata(false, PropertyChangedCallback));
public static void PropertyChangedCallback(DependencyObject depObj, DependencyPropertyChangedEventArgs args)
{
FrameworkElement element = (FrameworkElement)depObj;
if (element != null)
{
if ((bool)args.NewValue)
{
element.MouseDown += new MouseButtonEventHandler(element_MouseDown);
element.MouseUp += new MouseButtonEventHandler(element_MouseUp);
element.MouseLeave += new MouseEventHandler(element_MouseLeave);
}
else
{
element.MouseDown -= new MouseButtonEventHandler(element_MouseDown);
element.MouseUp -= new MouseButtonEventHandler(element_MouseUp);
element.MouseLeave -= new MouseEventHandler(element_MouseLeave);
}
}
}
static void element_MouseLeave(object sender, MouseEventArgs e)
{
FrameworkElement element = (FrameworkElement)sender;
if (element != null)
{
element.SetValue(IsPressedProperty, false);
}
}
static void element_MouseUp(object sender, MouseButtonEventArgs e)
{
FrameworkElement element = (FrameworkElement)sender;
if (element != null)
{
element.SetValue(IsPressedProperty, false);
}
}
static void element_MouseDown(object sender, MouseButtonEventArgs e)
{
FrameworkElement element = (FrameworkElement)sender;
if (element != null)
{
element.SetValue(IsPressedProperty, true);
}
}
public static bool GetIsPressed(UIElement element)
{
return (bool)element.GetValue(IsPressedProperty);
}
public static void SetIsPressed(UIElement element, bool val)
{
element.SetValue(IsPressedProperty, val);
}
public static bool GetAttachIsPressed(UIElement element)
{
return (bool)element.GetValue(AttachIsPressedProperty);
}
public static void SetAttachIsPressed(UIElement element, bool val)
{
element.SetValue(AttachIsPressedProperty, val);
}
}
public class ClickableBorder : Border
{
public static readonly RoutedEvent ClickEvent;
static ClickableBorder()
{
ClickEvent = ButtonBase.ClickEvent.AddOwner(typeof(ClickableBorder));
}
public event RoutedEventHandler Click
{
add { AddHandler(ClickEvent, value); }
remove { RemoveHandler(ClickEvent, value); }
}
protected override void OnMouseDown(MouseButtonEventArgs e)
{
base.OnMouseDown(e);
CaptureMouse();
}
protected override void OnMouseUp(MouseButtonEventArgs e)
{
base.OnMouseUp(e);
if (IsMouseCaptured)
{
ReleaseMouseCapture();
if (IsMouseOver)
{
RaiseEvent(new RoutedEventArgs(ClickEvent, this));
}
}
}
}
现在我从一些WPF教程中收集到的代码我已经阅读完了,因为我还没有牢牢掌握所附属性的工作原理等等。
基本上边框现在是可点击的并且具有IsPressed属性。后者将用作样式触发条件。所以目前我有三个样式设置器/动画对。
默认外观:
<Setter Property="BorderBrush" Value="Black"/>
<Setter Property="Background" Value="LightGray"/>
MouseOver看:
<ColorAnimation Duration="0:0:0.200" To="White" Storyboard.TargetProperty="BorderBrush.Color"/>
<ColorAnimation Duration="0:0:0.200" To="DarkGray" Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)"/>
IsPressed看起来:
<ColorAnimation Duration="0:0:0.200" To="DarkRed" Storyboard.TargetProperty="BorderBrush.Color"/>
<ColorAnimation Duration="0:0:0.200" To="Red" Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)"/>
现在的问题是,只要单击边框并执行IsPressed EnterActions和ExitActions,第一个MultiTrigger的动画就不再有效了。我的触发器,EnterActions和ExitActions显然是错误的,但我不知道它是什么。
非常感谢任何建议!
答案 0 :(得分:2)
使用<RemoveStoryboard>
作为退出操作:
<Style TargetType="{x:Type local:ClickableBorder}">
<Setter Property="BorderBrush" Value="Black"/>
<Setter Property="Background" Value="LightGray"/>
<Style.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsMouseOver" Value="True"/>
<Condition Property="IsEnabled" Value="True"/>
</MultiTrigger.Conditions>
<MultiTrigger.EnterActions>
<BeginStoryboard Name="sb">
<Storyboard>
<ColorAnimation Duration="0:0:0.200" To="White" Storyboard.TargetProperty="BorderBrush.Color"/>
<ColorAnimation Duration="0:0:0.200" To="DarkGray" Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)"/>
</Storyboard>
</BeginStoryboard>
</MultiTrigger.EnterActions>
<MultiTrigger.ExitActions>
<RemoveStoryboard BeginStoryboardName="sb" />
</MultiTrigger.ExitActions>
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="local:FrameworkElementExt.IsPressed" Value="True"/>
<Condition Property="IsEnabled" Value="True"/>
</MultiTrigger.Conditions>
<MultiTrigger.EnterActions>
<BeginStoryboard Name="sb2">
<Storyboard>
<ColorAnimation Duration="0:0:0.200" To="DarkRed" Storyboard.TargetProperty="BorderBrush.Color"/>
<ColorAnimation Duration="0:0:0.200" To="Red" Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)"/>
</Storyboard>
</BeginStoryboard>
</MultiTrigger.EnterActions>
<MultiTrigger.ExitActions>
<RemoveStoryboard BeginStoryboardName="sb2" />
</MultiTrigger.ExitActions>
</MultiTrigger>
</Style.Triggers>
</Style>
修改强>
好的,现在故事板为每个州正确设置颜色。但是,当执行ExitAction时,颜色现在突然改变而不是动画。我想让它在一段时间内制作动画,就像在EnterActions下一样。我怎么能这样做?
将退出FillBehavior
的{{1}}属性设置为Storyboards
:
Stop