问题描述
这是我第一次使用 non-rectangular 窗口和 WPF 中的动画,所以当我正在处理所有与实际游戏代码有关的错误时,我提交了 XAML 进行审查 – 我不喜欢多余这是,但我相信有一个聪明的方式来简化它。
<Window x:Class="SimonSays.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:simonSays="clr-namespace:SimonSays"
mc:Ignorable="d"
Height="480" Width="480"
AllowsTransparency="True" Background="Transparent" WindowStyle="None"
d:DataContext="{d:DesignInstance simonSays:SimonSaysRound}">
<Window.Clip>
<EllipseGeometry RadiusX="240" RadiusY="240" Center="242,242" />
</Window.Clip>
<Border Background="Black" BorderThickness="2">
<Border.Clip>
<EllipseGeometry Center="240,240" RadiusX="238" RadiusY="238" />
</Border.Clip>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<StackPanel x:Name="MessageBar" Grid.Row="1" Grid.ColumnSpan="2" Margin="4" Height="0">
<TextBlock x:Name="GameButton" Foreground="White" HorizontalAlignment="Center" FontSize="24" FontWeight="Bold" />
<TextBlock x:Name="GameScoreLabel" Text="{Binding Score, StringFormat=Your score: {0}}" Foreground="White" HorizontalAlignment="Center" FontWeight="Bold" IsEnabled="False" />
</StackPanel>
<Border x:Name="Green" Margin="1" CornerRadius="16" MouseDown="Green_MouseDown">
<Border.Clip>
<EllipseGeometry Center="240,240" RadiusX="240" RadiusY="240" />
</Border.Clip>
<Border.Style>
<Style>
<Setter Property="Border.Background">
<Setter.Value>
<RadialGradientBrush GradientOrigin="1,1" RadiusX="1" RadiusY="1">
<GradientStop Color="LightGreen" Offset="0.0" />
<GradientStop Color="DarkGreen" Offset="0.5" />
</RadialGradientBrush>
</Setter.Value>
</Setter>
<Style.Triggers>
<EventTrigger RoutedEvent="Border.MouseEnter">
<BeginStoryboard>
<Storyboard TargetProperty="Background.GradientStops[1].Offset" Duration="0:0:0.25">
<DoubleAnimation To="1.0" />
<Storyboard TargetProperty="Background.GradientStops[0].Offset">
<DoubleAnimation To="0.2" />
</Storyboard>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="Border.MouseLeave">
<BeginStoryboard>
<Storyboard TargetProperty="Background.GradientStops[1].Offset" Duration="0:0:0.25">
<DoubleAnimation To="0.5" />
<Storyboard TargetProperty="Background.GradientStops[0].Offset">
<DoubleAnimation To="0.0" />
</Storyboard>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Style.Triggers>
</Style>
</Border.Style>
</Border>
<Border Grid.Column="1" x:Name="Red" Margin="1" CornerRadius="16" MouseDown="Red_MouseDown">
<Border.Clip>
<EllipseGeometry Center="-4,240" RadiusX="240" RadiusY="240" />
</Border.Clip>
<Border.Style>
<Style>
<Setter Property="Border.Background">
<Setter.Value>
<RadialGradientBrush GradientOrigin="0,1" RadiusX="1" RadiusY="1">
<GradientStop Color="LightPink" Offset="0.0" />
<GradientStop Color="DarkRed" Offset="0.5" />
</RadialGradientBrush>
</Setter.Value>
</Setter>
<Style.Triggers>
<EventTrigger RoutedEvent="Border.MouseEnter">
<BeginStoryboard>
<Storyboard TargetProperty="Background.GradientStops[1].Offset" Duration="0:0:0.25">
<DoubleAnimation To="1.0" />
<Storyboard TargetProperty="Background.GradientStops[0].Offset">
<DoubleAnimation To="0.2" />
</Storyboard>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="Border.MouseLeave">
<BeginStoryboard>
<Storyboard TargetProperty="Background.GradientStops[1].Offset" Duration="0:0:0.25">
<DoubleAnimation To="0.5" />
<Storyboard TargetProperty="Background.GradientStops[0].Offset">
<DoubleAnimation To="0.0" />
</Storyboard>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Style.Triggers>
</Style>
</Border.Style>
</Border>
<Border Grid.Row="2" x:Name="Yellow" Margin="1" CornerRadius="16" MouseDown="Yellow_MouseDown">
<Border.Clip>
<EllipseGeometry Center="240,-4" RadiusX="240" RadiusY="240" />
</Border.Clip>
<Border.Style>
<Style>
<Setter Property="Border.Background">
<Setter.Value>
<RadialGradientBrush GradientOrigin="1,0" RadiusX="1" RadiusY="1">
<GradientStop Color="LightYellow" Offset="0.0" />
<GradientStop Color="Orange" Offset="0.5" />
</RadialGradientBrush>
</Setter.Value>
</Setter>
<Style.Triggers>
<EventTrigger RoutedEvent="Border.MouseEnter">
<BeginStoryboard>
<Storyboard TargetProperty="Background.GradientStops[1].Offset" Duration="0:0:0.25">
<DoubleAnimation To="1.0" />
<Storyboard TargetProperty="Background.GradientStops[0].Offset">
<DoubleAnimation To="0.2" />
</Storyboard>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="Border.MouseLeave">
<BeginStoryboard>
<Storyboard TargetProperty="Background.GradientStops[1].Offset" Duration="0:0:0.25">
<DoubleAnimation To="0.5" />
<Storyboard TargetProperty="Background.GradientStops[0].Offset">
<DoubleAnimation To="0.0" />
</Storyboard>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Style.Triggers>
</Style>
</Border.Style>
</Border>
<Border Grid.Row="2" Grid.Column="1" x:Name="Blue" Margin="1" CornerRadius="16" MouseDown="Blue_MouseDown">
<Border.Clip>
<EllipseGeometry Center="-4,-4" RadiusX="240" RadiusY="240" />
</Border.Clip>
<Border.Style>
<Style>
<Setter Property="Border.Background">
<Setter.Value>
<RadialGradientBrush GradientOrigin="0,0" RadiusX="1" RadiusY="1">
<GradientStop Color="LightSkyBlue" Offset="0.0" />
<GradientStop Color="Blue" Offset="0.5" />
</RadialGradientBrush>
</Setter.Value>
</Setter>
<Style.Triggers>
<EventTrigger RoutedEvent="Border.MouseEnter">
<BeginStoryboard>
<Storyboard TargetProperty="Background.GradientStops[1].Offset" Duration="0:0:0.25">
<DoubleAnimation To="1.0" />
<Storyboard TargetProperty="Background.GradientStops[0].Offset">
<DoubleAnimation To="0.2" />
</Storyboard>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="Border.MouseLeave">
<BeginStoryboard>
<Storyboard TargetProperty="Background.GradientStops[1].Offset" Duration="0:0:0.25">
<DoubleAnimation To="0.5" />
<Storyboard TargetProperty="Background.GradientStops[0].Offset">
<DoubleAnimation To="0.0" />
</Storyboard>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Style.Triggers>
</Style>
</Border.Style>
</Border>
</Grid>
</Border>
</Window>
结果是一个圆形窗口,四个象限和一个黑色的水平带,用作拖动窗户的手柄:
我也用它来显示消息,玩家的得分:
按钮/象限在消息频段扩展 (无法单击; 仍然对 mouse-over 做出反应) 时被禁用,而 re-enabled 在点击消息后崩溃。
没有控制箱,窗口只能通过点击”Game Over” 标签来关闭:
我在 code-behind 中有这个 C#代码 (还没有准备好审核的代码),用于动画按钮点击和消息带:
private void AnimateMessageBand(double height)
{
var animation = new DoubleAnimation(height, new Duration(TimeSpan.FromMilliseconds(200)));
RegisterName(MessageBar.Name, MessageBar);
Storyboard.SetTargetName(animation, MessageBar.Name);
Storyboard.SetTargetProperty(animation, new PropertyPath("Height"));
var story = new Storyboard();
story.Children.Add(animation);
story.Begin(MessageBar);
story.Remove();
}
private readonly IDictionary<SimonButton, Border> _buttons;
public void HighlightSimonButton(SimonButton button)
{
var animation = new DoubleAnimation(0, 0.75, new Duration(TimeSpan.FromMilliseconds(100)));
RegisterName(button.ToString(), _buttons[button]);
Storyboard.SetTargetName(animation, button.ToString());
Storyboard.SetTargetProperty(animation, new PropertyPath("Background.GradientStops[1].Offset"));
var story = new Storyboard();
story.Children.Add(animation);
story.Begin(_buttons[button]);
story.Remove();
}
最佳解决方案
-
您可以使用
Border
创建一个按钮,而不是使用具有自定义模板的实际Button
类。因此,您必须手动管理已经在常规Button
(Clicked
,IsPressed
,Command
,与IsEnabled
属性和键盘等的交互) 中实现的所有交互。所以我建议你使用一个实际的按钮。 -
那么你的故事板显然是 copy-pasted 。 :) 你为什么不把他们移动到资源?
参考文献
注:本文内容整合自 Google/Baidu/Bing 辅助翻译的英文资料结果。如果您对结果不满意,可以加入我们改善翻译效果:薇晓朵技术论坛。