我的WPF应用程序有一个我在blend上构建的样式管理器。
我的问题是:我有一个偶尔闪烁的登录按钮,我无法弄清楚如何消除这种行为。
这是我登录框的样式代码:
<Style x:Key="LoginBoxGrid" TargetType="{x:Type Grid}">
<Setter Property="Background">
<Setter.Value>
<ImageBrush ImageSource="/Client;component/Assets/images/LoginBox.png" Stretch="None" TileMode="Tile"/>
</Setter.Value>
</Setter>
<Setter Property="Opacity" Value="0.765"/>
<Setter Property="Width" Value="411"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="Margin" Value="126,150,0,111"/>
</Style>
<Style x:Key="LoginBoxHeader" TargetType="{x:Type Label}">
<Setter Property="Grid.Column" Value="2"/>
<Setter Property="Margin" Value="-16.183,18.347,0,0"/>
<Setter Property="Width" Value="64.994"/>
<Setter Property="FontSize" Value="16"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="FontStyle" Value="Italic"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="VerticalAlignment" Value="Top"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="FontFamily" Value="/Client;component/Assets/Fonts/#Arial Black"/>
</Style>
<Style x:Key="LoginBtn" TargetType="{x:Type Button}">
<Setter Property="Grid.Column" Value="2"/>
<Setter Property="Margin" Value="16.6,9.022,9.282,8"/>
<Setter Property="Grid.Row" Value="4"/>
<Setter Property="Width" Value="164"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Opacity" Value="0.78"/>
<Setter Property="IsDefault" Value="True"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="Background">
<Setter.Value>
<ImageBrush ImageSource="/Client;component/Assets/images/LoginBtn.png"/>
</Setter.Value>
</Setter>
</Style>
这是我的窗口代码:
<Grid Style="{StaticResource LoginBoxGrid}" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.127*"/>
<ColumnDefinition Width="0.326*"/>
<ColumnDefinition Width="0.462*"/>
<ColumnDefinition Width="0.085*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="0.269*"/>
<RowDefinition Height="0.028*"/>
<RowDefinition Height="0.256*"/>
<RowDefinition Height="0.223*"/>
<RowDefinition Height="0.178*"/>
<RowDefinition Height="0.046*"/>
</Grid.RowDefinitions>
<Label Content="User Name" Grid.Column="1" Margin="43.986,23.1,8,8" Grid.Row="2" Width="82" BorderThickness="0" FontFamily="Arial" FontWeight="Bold" FontStyle="Italic"/>
<Label Content="Password" Grid.Column="1" Margin="43.986,15.873,8,8" Grid.Row="3" Width="82" BorderThickness="0" FontFamily="Arial" FontWeight="Bold" FontStyle="Italic"/>
<PasswordBox Grid.Column="2" Name="PassTb" HorizontalAlignment="Left" Margin="8,18.877,0,8" Grid.Row="3" Width="172.6" d:LayoutOverrides="Height"/>
<TextBox Grid.Column="2" Name="UserTb" HorizontalAlignment="Left" Margin="9.282,23.1,0,11.004" Grid.Row="2" TextWrapping="Wrap" Text="TextBox" Width="172.6" d:LayoutOverrides="Height"/>
<Label Style="{StaticResource LoginBoxHeader}" Content="Login" />
<Button Name="LoginBtn" Style="{StaticResource LoginBtn}" Content="Login" />
</Grid>
我正在谈论的Button被称为“LoginBtn”,它的风格也是如此。
如何删除闪烁行为?提前谢谢。
答案 0 :(得分:10)
闪烁是由于WPF用于按钮的默认样式。更具体地说,这是由于按钮的控制模板上的触发器。要删除它,请进入混合,右键单击按钮并选择“编辑模板” - >“编辑副本”。单击内容呈现器的子元素(默认情况下,这是名为“Chrome”的控件)。然后,在触发器选项卡中,通过按“ - trigger”激活RenderDefaulted。该触发器将使按钮不闪烁。如果您只想要XAML,那么它将由windows.resource ...
包装<Window.Resources>
<Style x:Key="ButtonFocusVisual">
<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>
<LinearGradientBrush x:Key="ButtonNormalBackground" EndPoint="0,1" StartPoint="0,0">
<GradientStop Color="#F3F3F3" Offset="0"/>
<GradientStop Color="#EBEBEB" Offset="0.5"/>
<GradientStop Color="#DDDDDD" Offset="0.5"/>
<GradientStop Color="#CDCDCD" Offset="1"/>
</LinearGradientBrush>
<SolidColorBrush x:Key="ButtonNormalBorder" Color="#FF707070"/>
<Style x:Key="BoringButtonStyle" TargetType="{x:Type Button}">
<Setter Property="FocusVisualStyle" Value="{StaticResource ButtonFocusVisual}"/>
<Setter Property="Background" Value="{StaticResource ButtonNormalBackground}"/>
<Setter Property="BorderBrush" Value="{StaticResource ButtonNormalBorder}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Padding" Value="1"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Microsoft_Windows_Themes:ButtonChrome x:Name="Chrome" BorderBrush="{TemplateBinding BorderBrush}" Background="{TemplateBinding Background}" RenderMouseOver="{TemplateBinding IsMouseOver}" RenderPressed="{TemplateBinding IsPressed}" RenderDefaulted="{TemplateBinding IsDefaulted}" SnapsToDevicePixels="true">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Microsoft_Windows_Themes:ButtonChrome>
<ControlTemplate.Triggers>
<Trigger Property="ToggleButton.IsChecked" Value="true">
<Setter Property="RenderPressed" TargetName="Chrome" Value="true"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="#ADADAD"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
然后,无论你在哪里按钮,都应用这种风格......
<Button Style="{DynamicResource BoringButtonStyle}"/>
更新:多年来,默认按钮样式发生了变化。这个想法是一样的,使用Blend for Visual Studio来编辑你想要改变的元素的模板。对于此按钮,只需简单地删除IsDefaulted触发器。这是一个更新的代码段。
<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="#FFDDDDDD"/>
<SolidColorBrush x:Key="Button.Static.Border" Color="#FF707070"/>
<SolidColorBrush x:Key="Button.MouseOver.Background" Color="#FFBEE6FD"/>
<SolidColorBrush x:Key="Button.MouseOver.Border" Color="#FF3C7FB1"/>
<SolidColorBrush x:Key="Button.Pressed.Background" Color="#FFC4E5F6"/>
<SolidColorBrush x:Key="Button.Pressed.Border" Color="#FF2C628B"/>
<SolidColorBrush x:Key="Button.Disabled.Background" Color="#FFF4F4F4"/>
<SolidColorBrush x:Key="Button.Disabled.Border" Color="#FFADB2B5"/>
<SolidColorBrush x:Key="Button.Disabled.Foreground" Color="#FF838383"/>
<Style x:Key="BoringButtonStyle" TargetType="{x:Type Button}">
<Setter Property="FocusVisualStyle" Value="{StaticResource FocusVisual}"/>
<Setter Property="Background" Value="{StaticResource Button.Static.Background}"/>
<Setter Property="BorderBrush" Value="{StaticResource Button.Static.Border}"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Padding" Value="1"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="true">
<ContentPresenter x:Name="contentPresenter" Focusable="False" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
<ControlTemplate.Triggers>
<!-- Delete this trigger
<Trigger Property="IsDefaulted" Value="true">
<Setter Property="BorderBrush" TargetName="border" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
</Trigger>-->
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Background" TargetName="border" Value="{StaticResource Button.MouseOver.Background}"/>
<Setter Property="BorderBrush" TargetName="border" Value="{StaticResource Button.MouseOver.Border}"/>
</Trigger>
<Trigger Property="IsPressed" Value="true">
<Setter Property="Background" TargetName="border" Value="{StaticResource Button.Pressed.Background}"/>
<Setter Property="BorderBrush" TargetName="border" Value="{StaticResource Button.Pressed.Border}"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Background" TargetName="border" Value="{StaticResource Button.Disabled.Background}"/>
<Setter Property="BorderBrush" TargetName="border" Value="{StaticResource Button.Disabled.Border}"/>
<Setter Property="TextElement.Foreground" TargetName="contentPresenter" Value="{StaticResource Button.Disabled.Foreground}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
答案 1 :(得分:9)
简单解决方案:将按钮的“可聚焦”设置为False。
答案 2 :(得分:5)
稍微不那么突兀的删除闪烁的方法是为ControlTemplate
设置新的ButtonBase
并删除违规绑定。
我从Button默认样式中通过StyleSnooper获取此内容,并将其修改/简化为ButtonBase的样式,它只提供了一个新的ControlTemplate *。为此,请向Presentation.Aero 添加程序集引用,并在ResourceDictionary中引入Microsoft.Windows.Themes名称空间。
在这里,我通过将IsDefault
硬编码为false,专门删除了受影响的Button在其RenderDefaulted
属性上“闪烁”的功能。你可能还想替换RenderMouseOver
TemplateBinding。
<ResourceDictionary [...]
xmlns:mwt="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero">
<Style TargetType="{x:Type ButtonBase}"
x:Key="NonBlinkingButtonBase">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ButtonBase}">
<mwt:ButtonChrome Background="{TemplateBinding Panel.Background}"
BorderBrush="{TemplateBinding Border.BorderBrush}"
RenderDefaulted="False"
RenderMouseOver="{TemplateBinding UIElement.IsMouseOver}"
RenderPressed="{TemplateBinding ButtonBase.IsPressed}"
Name="Chrome"
SnapsToDevicePixels="True">
<ContentPresenter RecognizesAccessKey="True"
Content="{TemplateBinding ContentControl.Content}"
ContentTemplate="{TemplateBinding ContentControl.ContentTemplate}"
ContentStringFormat="{TemplateBinding ContentControl.ContentStringFormat}"
Margin="{TemplateBinding Control.Padding}"
HorizontalAlignment="{TemplateBinding Control.HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding Control.VerticalContentAlignment}"
SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" />
</mwt:ButtonChrome>
<ControlTemplate.Triggers>
<Trigger Property="UIElement.IsKeyboardFocused" Value="True">
<Setter Property="mwt:ButtonChrome.RenderDefaulted" TargetName="Chrome" Value="True" />
</Trigger>
<Trigger Property="ToggleButton.IsChecked" Value="True">
<Setter Property="mwt:ButtonChrome.RenderPressed" TargetName="Chrome" Value="True" />
</Trigger>
<Trigger Property="UIElement.IsEnabled" Value="False">
<Setter Property="TextElement.Foreground">
<Setter.Value>
<SolidColorBrush>
#FFADADAD</SolidColorBrush>
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
然后将此样式用作Button的BasedOn:
<Style x:Key="LoginBtn"
TargetType="{x:Type Button}"
BasedOn="{StaticResource NonBlinkingButtonBase}">
[...your stuff...]
</Style>
(*)是的,我们应该真的有能力使用BasedOn用于ControlTemplates ......
答案 3 :(得分:1)
我自从我的第一个答案在将图像附加到按钮时遇到了这个问题,我想通过设置图像和按钮来拉伸并使用边框上的尺寸来解决问题。
示例代码..
<Border Width="45" Height="45">
<Button x:Name="buttonSend"
ToolTip="Send" Command="{Binding Path=SendCommand}" Style="{StaticResource actionButtonStyle}">
<Image Source="..\Images\Email-256.png" Stretch="Fill" />
</Button>