我正在尝试在WPF中实现自定义控件按钮,灵感来自材质设计。按住按钮时,应该有一个不断增长的圆圈,您可以从中单击它。我在下面的代码中成功实现了它,但是在第二个按钮保持(鼠标按下)之后,动画被冻结。
XAML:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:LiteWpfControls"
xmlns:Converters="clr-namespace:LiteWpfControls.Converters"
xmlns:ed="http://schemas.microsoft.com/expression/2010/drawing">
<Converters:ArithmeticConverter x:Key="ArithmeticConverter"/>
<Converters:ColorConverter x:Key="ColorConverter"/>
<Style x:Key="FocusVisual">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Rectangle Margin="2" SnapsToDevicePixels="true" Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" StrokeThickness="1" StrokeDashArray="1 2"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<SolidColorBrush x:Key="Button.Static.Background" Color="#e67e22"/>
<SolidColorBrush x:Key="Button.Static.Foreground" Color="White"/>
<SolidColorBrush x:Key="Button.Pressed.Background" Color="#FFC4E5F6"/>
<SolidColorBrush x:Key="Button.Disabled.Background" Color="#FFF4F4F4"/>
<SolidColorBrush x:Key="Button.Disabled.Foreground" Color="#FF838383"/>
<Style TargetType="{x:Type local:MaterialButton}">
<Setter Property="FocusVisualStyle" Value="{StaticResource FocusVisual}"/>
<Setter Property="Background" Value="{StaticResource Button.Static.Background}"/>
<Setter Property="Foreground" Value="{StaticResource Button.Static.Foreground}"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Padding" Value="1"/>
<Setter Property="SnapsToDevicePixels" Value="True"/>
<Setter Property="IsDefault" Value="True"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:MaterialButton}">
<ControlTemplate.Resources>
<Storyboard x:Key="sbLoader">
<DoubleAnimationUsingKeyFrames RepeatBehavior="Forever" Storyboard.TargetProperty="(ed:Arc.StartAngle)" Storyboard.TargetName="arcLoading">
<EasingDoubleKeyFrame KeyTime="0" Value="0"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="360"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames RepeatBehavior="Forever" Storyboard.TargetProperty="(ed:Arc.EndAngle)" Storyboard.TargetName="arcLoading">
<EasingDoubleKeyFrame KeyTime="0" Value="180"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="540"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</ControlTemplate.Resources>
<Grid Width="{TemplateBinding Width}" Height="{TemplateBinding Height}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}">
<Border x:Name="bdrBorder" SnapsToDevicePixels="true" Background="{TemplateBinding Background}"
CornerRadius="{Binding ActualHeight, ConverterParameter=/2, Converter={StaticResource ArithmeticConverter}, Mode=OneWay, RelativeSource={RelativeSource Self}}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="{Binding CornerRadius.BottomLeft, ElementName=bdrBorder}"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="{Binding CornerRadius.BottomRight, ElementName=bdrBorder}"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="10*"/>
<RowDefinition Height="80*"/>
<RowDefinition Height="10*"/>
</Grid.RowDefinitions>
<Border x:Name="bdrBorderBg" Grid.ColumnSpan="3" Grid.RowSpan="3" CornerRadius="{Binding CornerRadius, ElementName=bdrBorder}">
<Border.Background>
<RadialGradientBrush x:Name="bshBorderBg" GradientOrigin="{Binding Center, RelativeSource={RelativeSource Self}}" MappingMode="Absolute" RadiusY="{Binding RadiusX, RelativeSource={RelativeSource Self}}" RadiusX="0">
<GradientStop Offset="0.5" Color="#55000000"/>
<GradientStop Offset="0.5" Color="{Binding Background, ConverterParameter=tc0, Converter={StaticResource ColorConverter}, ElementName=bdrBorder}"/>
</RadialGradientBrush>
<Border.Background>
</Border>
<ContentPresenter x:Name="cpContent" Focusable="False" HorizontalAlignment="Center"
VerticalAlignment="Center" Grid.RowSpan="1" Grid.ColumnSpan="1" Grid.Column="1" Grid.Row="1"/>
<Border x:Name="bdrPressed" Width="0" Background="#40000000" SnapsToDevicePixels="true"
CornerRadius="{Binding ActualHeight, ConverterParameter=/2, Converter={StaticResource ArithmeticConverter}, Mode=OneWay, RelativeSource={RelativeSource Self}}"
Grid.RowSpan="3" Grid.Column="1"/>
<Grid Grid.RowSpan="3" Grid.ColumnSpan="3">
<Grid.RowDefinitions>
<RowDefinition Height="17.5*"/>
<RowDefinition Height="65*"/>
<RowDefinition Height="17.5*"/>
</Grid.RowDefinitions>
<ed:Arc x:Name="arcLoading" Opacity="0" Stroke="{TemplateBinding Foreground}" EndAngle="180" Stretch="None" StartAngle="0" Width="{Binding ActualHeight, ElementName=arcLoading}" SnapsToDevicePixels="True" Grid.Row="1"/>
</Grid>
</Grid>
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Background" TargetName="bdrBorder" Value="{Binding Background, ConverterParameter=lc50, Converter={StaticResource ColorConverter}, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:MaterialButton}}}"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Background" TargetName="bdrBorder" Value="{StaticResource Button.Disabled.Background}"/>
<Setter Property="TextElement.Foreground" TargetName="cpContent" Value="{StaticResource Button.Disabled.Foreground}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
部分代码:
protected override void OnMouseDown(MouseButtonEventArgs e)
{
var aniPressed = new DoubleAnimation(0, ActualWidth, new TimeSpan(0, 0, 0, 0, 500));
bshBorderBg.Center = e.GetPosition(this);
bshBorderBg.BeginAnimation(RadialGradientBrush.RadiusXProperty, aniPressed);
base.OnMouseUp(e);
}
protected override void OnMouseUp(MouseButtonEventArgs e)
{
var aniFade = new DoubleAnimation(1, 0, new TimeSpan(0, 0, 0, 0, 400));
bshBorderBg.BeginAnimation(RadialGradientBrush.OpacityProperty, aniFade);
base.OnMouseUp(e);
}
我想知道我哪里出错了。顺便说一句,我只是从WinForms迁移到了WPF的超棒程。