Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Blinking button on WPF application

My WPF application has a style manager that I have built on blend.

My problem is this: I've got a login button that blinks occasionally and i can't figure out how to remove this behavior.

Here's the style code for my login box:

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

And here's my code for the window:

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

The Button I'm talking about is called "LoginBtn", as is its style.

How can I remove that blinking behavior? Thanks in advance.

like image 751
Sivan Wolberg Avatar asked Oct 20 '10 13:10

Sivan Wolberg


2 Answers

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>
like image 104
Onosa Avatar answered Oct 08 '22 04:10

Onosa


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

like image 9
The Dreamer Avatar answered Oct 08 '22 04:10

The Dreamer