【发布时间】:2017-08-10 08:28:13
【问题描述】:
我想给 Border 一个类似按钮的行为,因为我想应用不对称的圆形边缘并摆脱标准按钮的焦点闪烁效果。当鼠标悬停在它上面并单击它时,我想对其应用不同的样式。除了两种样式之间的过渡外,它运行良好。考虑以下 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 教程中收集了背后的代码,因为我还没有牢牢掌握附加属性的工作原理等等。
Border 现在基本上是可点击的并且具有 IsPressed 属性。后者将用作样式触发条件。所以目前我有三个样式设置器/动画对。
默认外观:
<Setter Property="BorderBrush" Value="Black"/>
<Setter Property="Background" Value="LightGray"/>
鼠标悬停查看:
<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)"/>
现在的问题是,一旦单击 Border 并执行 IsPressed EnterActions 和 ExitActions,第一个 MultiTrigger 的动画就不再起作用了。显然我的触发器、EnterActions 和 ExitActions 有问题,但我不知道是什么。
非常感谢任何建议!
【问题讨论】: