我已经开始通过重新模板化主窗口的镶边来构建Wpf应用程序。我的chrome模板包含4个按钮,每个按钮都有一个模板,这些模板显示内部带有图像的边框,并使用触发器和彩色动画对边框重新着色以提供鼠标悬停效果。模板的其余部分是静态的,窗口的内容是一个按钮(仅用于显示内容)。我确实将AllowTransparency设置为True。
我遇到的问题是,当窗口较小(例如800w x 500h)时,动画运行良好,它们从鼠标进入并以正确速度播放的那一刻开始,但是当我增大窗口时,动画会变慢然后开始会滞后于鼠标进入按钮的位置,直到窗口最大化为止,在此之前,您必须让鼠标在动画播放之前以及当它非常生涩且缓慢时,在按钮上停留一段时间。
我已经尝试了以下方法来查找此问题,但无济于事:
我猜想wpf重绘的次数超出了我的预期,但我不知道在这种情况下如何停止重绘。
任何帮助都会受到欢迎。 对不起,Xaml列表很大。
窗口:
<Window x:Class="Shell"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
WindowState="{Binding ShellState,
Mode=OneWayToSource}"
Title="{Binding Title,
Mode=OneTime}"
Style="{Binding ShellStyling,
Mode=OneTime}"
WindowStartupLocation="CenterScreen"><!-- ShellStyling = MainWindowShellStyle-->
<WindowChrome.WindowChrome>
<WindowChrome CaptionHeight="{Binding TitleHeight,
Mode=OneTime}"
ResizeBorderThickness="{Binding ResizeBorderThickness,
Mode=OneTime}"
GlassFrameThickness="0"/>
</WindowChrome.WindowChrome>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<ContentControl Name="Stage"
Grid.Column="0"
Grid.Row="1"/>
</Grid>
</Window>
样式:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style x:Key = "ChromeButtonBaseStyle"
TargetType = "{x:Type Button}">
<Setter Property = "Template"
Value = "{StaticResource MizedButtonTemplate}"/>
<Setter Property = "WindowChrome.IsHitTestVisibleInChrome"
Value = "True"/>
<Setter Property = "SnapsToDevicePixels"
Value = "True"/>
<Setter Property = "ToolTipService.Placement"
Value = "Bottom"/>
<Setter Property = "ToolTipService.ShowOnDisabled"
Value = "True"/>
<Setter Property = "VerticalAlignment"
Value = "Bottom"/>
<Setter Property = "HorizontalAlignment"
Value = "Center"/>
</Style>
<Style x:Key = "ChromeButtonImageBaseStyle"
TargetType = "Image">
<Setter Property = "SnapsToDevicePixels"
Value = "True"/>
<Setter Property = "ToolTipService.Placement"
Value = "Bottom"/>
<Setter Property = "Stretch"
Value = "None"/>
<Setter Property = "RenderOptions.BitmapScalingMode"
Value = "NearestNeighbor"/>
<Setter Property = "WindowChrome.IsHitTestVisibleInChrome"
Value = "True"/>
</Style>
<Style x:Key = "ChromeButtonImageStyle"
TargetType = "Image"
BasedOn = "{StaticResource ChromeButtonImageBaseStyle}">
<Setter Property = "Height"
Value = "{Binding ImageHeight,
Mode=OneTime}"/>
<Setter Property = "Width"
Value = "{Binding ImageWidth,
Mode=OneTime}"/>
</Style>
<Style x:Key = "ChromeButtonsContainerStyle"
TargetType = "Border">
<Setter Property = "Background"
Value = "{StaticResource BackgroundBrush}"/>
</Style>
<Style x:Key = "ChromeButtonsInnerContainerStyle"
TargetType = "{x:Type StackPanel}">
<Setter Property = "Orientation"
Value = "Horizontal"/>
<Setter Property = "VerticalAlignment"
Value = "Bottom"/>
</Style>
<Style TargetType = "{x:Type Button}"
x:Key = "ChromeButtonStyle"
BasedOn = "{StaticResource ChromeButtonBaseStyle}">
<Setter Property = "Border.CornerRadius"
Value = "{Binding CornerRadius,
Mode=OneTime}"/>
<Setter Property = "Padding"
Value = "{Binding ImagePadding,
Mode=OneTime}"/>
<Setter Property = "Margin"
Value = "{Binding ImageMargin,
Mode=OneTime}"/>
<Setter Property = "ToolTipService.VerticalOffset"
Value = "{Binding ToolTipVerticalOffset,
Mode=OneTime}"/>
<Setter Property = "ToolTipService.HorizontalOffset"
Value = "{Binding ToolTipHorizontalOffset,
Mode=OneTime}"/>
</Style>
<Style TargetType = "{x:Type Button}"
x:Key = "CloseButtonStyle"
BasedOn = "{StaticResource ChromeButtonStyle}">
<Setter Property = "Template"
Value = "{StaticResource CloseButtonTemplate}"/>
<Setter Property = "ToolTipService.ToolTip"
Value = "{Binding ToolTipText}"/>
<EventSetter Event = "Click"
Handler = "HandleCloseWindow" />
</Style>
<Style x:Key = "ContainerGridStyle"
TargetType = "Grid">
<Setter Property = "Background"
Value = "Transparent"/>
</Style>
<Style x:Key = "ContentContainerStyle"
TargetType = "Border">
<Setter Property = "Background"
Value = "{StaticResource BackgroundBrush}"/>
</Style>
<Style x:Key = "GripHandleStyle"
TargetType = "Image">
<Setter Property = "Width"
Value = "{Binding GripHandleWidth,
Mode=OneTime}"/>
<Setter Property = "Height"
Value = "{Binding TitleHeight,
Mode=OneTime}"/>
<Setter Property = "Stretch"
Value = "None"/>
<Setter Property = "SnapsToDevicePixels"
Value = "True"/>
<Setter Property = "Margin"
Value = "0"/>
<Setter Property = "HorizontalAlignment"
Value = "Right"/>
<Setter Property = "Source"
Value = "{Binding GripHandleDefinition,
Mode=OneTime}"/>
<Setter Property = "RenderOptions.BitmapScalingMode"
Value = "NearestNeighbor"/>
</Style>
<Style x:Key = "InnerBorderStyle"
TargetType = "{x:Type Border}">
<Setter Property = "Effect">
<Setter.Value>
<DropShadowEffect ShadowDepth = "0"
BlurRadius = "8"
RenderingBias = "Quality"/>
</Setter.Value>
</Setter>
</Style>
<Style x:Key = "MaximizeButtonStyle"
TargetType = "Button"
BasedOn = "{StaticResource ChromeButtonStyle}">
<Setter Property = "ToolTipService.ToolTip"
Value = "{Binding ToolTipText}"/>
<EventSetter Event = "Click"
Handler = "HandleMaximizeWindow"/>
</Style>
<Style x:Key = "MinimizeButtonStyle"
TargetType = "Button"
BasedOn = "{StaticResource ChromeButtonStyle}">
<Setter Property = "ToolTipService.ToolTip"
Value = "{Binding ToolTipText}"/>
<EventSetter Event = "Click"
Handler = "HandleMinimizeWindow"/>
</Style>
<Style x:Key = "OuterBorderStyle"
TargetType = "{x:Type Border}">
<Setter Property = "BorderThickness"
Value = "0"/>
<Setter Property = "BorderBrush"
Value = "{x:Null}"/>
<Setter Property = "Background"
Value = "Transparent"/>
<Setter Property = "Padding"
Value = "{Binding RelativeSource = {RelativeSource TemplatedParent},
Path=DataContext.OuterMarginThickness,
Mode=OneWay}"/>
</Style>
<Style x:Key = "TitleLayoutStyle"
TargetType = "StackPanel">
<Setter Property = "Orientation"
Value = "Horizontal"/>
<Setter Property = "Height"
Value = "{Binding TitleHeight,
Mode=OneTime}"/>
</Style>
<Style x:Key = "TitleTextBaseStyle"
TargetType = "{x:Type TextBlock}">
<Setter Property = "FontFamily"
Value = "Segoe UI"/>
<Setter Property = "Foreground"
Value = "{StaticResource TitleBrush}"/>
<Setter Property = "VerticalAlignment"
Value = "Bottom"/>
<Setter Property = "Background"
Value = "Transparent"/>
<Setter Property = "Text"
Value = "{Binding Title,
Mode=OneTime}"/>
</Style>
<Style x:Key = "TitleTextStyle"
TargetType = "TextBlock"
BasedOn = "{StaticResource TitleTextBaseStyle}">
<Setter Property = "FontSize"
Value = "{Binding TitleTextFontSize,
Mode=OneTime}"/>
<Setter Property = "Margin"
Value = "{Binding TitleTextMargin,
Mode=OneTime}"/>
</Style>
<Style x:Key = "WindowShellBaseStyle"
TargetType = "{x:Type Window}">
<Setter Property = "OverridesDefaultStyle"
Value = "True"/>
<Setter Property = "WindowStyle"
Value = "None"/>
<Setter Property = "AllowsTransparency"
Value = "True"/>
</Style>
<Style x:Key = "MainWindowShellStyle"
TargetType = "{x:Type Window}"
BasedOn = "{StaticResource WindowShellBaseStyle}">
<Setter Property = "Height"
Value = "{Binding Height}"/>
<Setter Property = "Width"
Value = "{Binding Width}"/>
<Setter Property = "MaxHeight"
Value = "{Binding MaxHeight}"/>
<Setter Property = "MaxWidth"
Value = "{Binding MaxWidth}"/>
<Setter Property = "MinHeight"
Value = "{Binding MinHeight}"/>
<Setter Property = "MinWidth"
Value = "{Binding MinWidth}"/>
<Setter Property = "ShowInTaskbar"
Value = "{Binding ShowInTaskBar}"/>
</Style>
</ResourceDictionary>
模板:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary
Source = "pack://application:,,,/WindowChromeColors.xaml"/>
<ResourceDictionary
Source = "pack://application:,,,/WindowChromeAnimations.xaml"/>
</ResourceDictionary.MergedDictionaries>
<ControlTemplate TargetType = "{x:Type Button}"
x:Key = "CloseButtonTemplate">
<Border Padding = "{TemplateBinding Padding}"
Margin = "{TemplateBinding Margin}"
BorderThickness = "{TemplateBinding BorderThickness}"
CornerRadius = "{TemplateBinding Border.CornerRadius}"
HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
VerticalAlignment="{TemplateBinding VerticalAlignment}"
SnapsToDevicePixels = "True">
<Border.BorderBrush>
<SolidColorBrush x:Name = "HoverBorderColor"
Color = "{StaticResource MouseOutBorder}"/>
</Border.BorderBrush>
<Border.Background>
<SolidColorBrush x:Name = "ButtonBackground"
Color = "{StaticResource Background}"/>
</Border.Background>
<Image Source="{Binding ImageSource}"
Style="{Binding ImageStyle}" />
</Border>
<ControlTemplate.Triggers>
<EventTrigger RoutedEvent = "MouseEnter">
<BeginStoryboard>
<Storyboard TargetName = "HoverBorderColor">
<!-- ReSharper disable once Xaml.InvalidResourceType -->
<StaticResource ResourceKey = "HoverBorderAnimation"/>
</Storyboard>
</BeginStoryboard>
<BeginStoryboard>
<Storyboard TargetName = "ButtonBackground">
<!-- ReSharper disable once Xaml.InvalidResourceType -->
<StaticResource ResourceKey = "CloseButtonHoverBgAnimation"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent = "MouseLeave">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard TargetName = "HoverBorderColor">
<!-- ReSharper disable once Xaml.InvalidResourceType -->
<StaticResource ResourceKey = "LeaveBorderAnimation"/>
</Storyboard>
</BeginStoryboard>
<BeginStoryboard>
<Storyboard TargetName = "ButtonBackground">
<!-- ReSharper disable once Xaml.InvalidResourceType -->
<StaticResource ResourceKey = "CloseButtonLeaveBgAnimation"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<ControlTemplate TargetType="{x:Type Button}"
x:Key="MizedButtonTemplate">
<Border Padding="{TemplateBinding Padding}"
Margin="{TemplateBinding Margin}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{TemplateBinding Border.CornerRadius}"
HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
VerticalAlignment="{TemplateBinding VerticalAlignment}"
SnapsToDevicePixels="True"
Background="{StaticResource BackgroundBrush}"
>
<Border.BorderBrush>
<SolidColorBrush x:Name="HoverBorderColor"
Color="{StaticResource MouseOutBorder}" />
</Border.BorderBrush>
<Image Source="{Binding ImageSource}"
Style="{Binding ImageStyle}"/>
</Border>
<ControlTemplate.Triggers>
<EventTrigger RoutedEvent="MouseEnter">
<BeginStoryboard>
<Storyboard TargetName="HoverBorderColor">
<!--ReSharper disable once Xaml.InvalidResourceType-->
<StaticResource ResourceKey="HoverBorderAnimation" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="MouseLeave">
<BeginStoryboard>
<Storyboard TargetName="HoverBorderColor">
<!--ReSharper disable once Xaml.InvalidResourceType-->
<StaticResource ResourceKey="LeaveBorderAnimation" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<ControlTemplate x:Key="WindowShellTemplate"
TargetType="{x:Type Window}">
<Border Style="{StaticResource OuterBorderStyle}">
<Border Style="{StaticResource InnerBorderStyle}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Grid.Column="0"
Grid.Row="0"
Style="{StaticResource ContainerGridStyle}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Image Grid.Column="0"
Grid.Row="0"
Style="{StaticResource GripHandleStyle}"/>
<Border Grid.Column="2"
Grid.Row="0"
Style="{StaticResource ChromeButtonsContainerStyle}">
<StackPanel Style="{StaticResource ChromeButtonsInnerContainerStyle}">
<TextBlock Grid.Column="1"
Grid.Row="0"
Style="{StaticResource TitleTextStyle}" />
<Button DataContext="{Binding MinimizeButtonViewModel,
Mode=OneTime}"
Style="{StaticResource MinimizeButtonStyle}"
Visibility="{Binding Visibility,
Mode=OneTime}"
Tag = "{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type Window}},
Mode=OneTime}" />
<Button DataContext="{Binding MaximizeButtonViewModel,
Mode=OneTime}"
Style="{StaticResource MaximizeButtonStyle}"
Visibility="{Binding Visibility,
Mode=OneTime}"
Tag = "{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type Window}},
Mode=OneTime}" />
<Button DataContext="{Binding CloseButtonViewModel,
Mode=OneTime}"
Style="{StaticResource CloseButtonStyle}"
Visibility="{Binding Visibility,
Mode=OneTime}"
Tag="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type Window}},
Mode=OneWay}"
Command = "{Binding ClickAction,
Mode=OneTime}"
CommandParameter = "{Binding RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType={x:Type Window}},
Mode=OneTime}" />
</StackPanel>
</Border>
</Grid>
<Border Grid.Column="0"
Grid.Row="1"
Style="{StaticResource ContentContainerStyle}">
<ContentPresenter />
</Border>
</Grid>
</Border>
</Border>
</ControlTemplate>
</ResourceDictionary>
动画所有颜色的动画与下面的动画相同,只是它们为不同的颜色设置动画。
<ColorAnimation x:Key="HoverBorderAnimation"
Storyboard.TargetProperty="Color"
To="{StaticResource MouseHoverBorder}"
Duration="0:0:0.25"
AutoReverse="False" />