Blinking button on WPF application Blinking button on WPF application wpf wpf

Blinking button on WPF application


That flashing is due to the default style that WPF uses for buttons. To be more specific, it's due to the Trigger on the button's control template. To remove this, go into blend, right click on the button and select "Edit Template"->"Edit a copy". Click on the child element of the content presenter (by default, this is the control called "Chrome"). Then, in the triggers tab, inactive RenderDefaulted by pressing "- trigger". That trigger will keep the button from blinking. If you just want the XAML for all of that, here it is wrapped by 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>

Then, wherever you button is, apply this style...

<Button Style="{DynamicResource BoringButtonStyle}"/>

Update: The default button style has changed over the years. The idea is the same, use Blend for Visual Studio to edit the templete of the element you want to change. For this button, simply remove the IsDefaulted trigger entirly. Here is an updated code snippet.

<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>


Simple solution: Set button's "Focusable" to False.


A slightly less obtrusive way of removing that blinking would be to set a new ControlTemplate for ButtonBase with the offending bindings removed.

I took this via StyleSnooper from the Button default Style and revamped/simplified it to be a Style for ButtonBase that simply provides a new ControlTemplate*. To do this, add an assembly reference to Presentation.Aero and introduce the Microsoft.Windows.Themes namespace in your ResourceDictionary.

Here, I specifically removed the affected Button's ability to "blink" on its IsDefault property by hardcoding RenderDefaulted to false; you'll probably also want to replace the 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>

Then use this style as a BasedOn for your Button:

<Style x:Key="LoginBtn"        TargetType="{x:Type Button}"        BasedOn="{StaticResource NonBlinkingButtonBase}">[...your stuff...]</Style>

(*) And yes, we should really have the ability to use BasedOn for ControlTemplates as well...