Мигающая кнопка в приложении WPF - PullRequest
14 голосов
/ 20 октября 2010

В моем приложении 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>

Кнопка, о которой я говорю, этоназывается "LoginBtn", как и его стиль.

Как я могу удалить это мигающее поведение?Заранее спасибо.

Ответы [ 4 ]

10 голосов
/ 06 марта 2011

Это мигание происходит из-за стиля по умолчанию, который WPF использует для кнопок.Чтобы быть более конкретным, это связано с триггером на шаблоне управления кнопки.Чтобы удалить это, перейдите в blend, щелкните правой кнопкой мыши на кнопке и выберите «Edit Template» -> «Edit a copy».Нажмите на дочерний элемент предъявителя контента (по умолчанию этот элемент управления называется «Chrome»).Затем на вкладке триггеров, неактивный RenderDefaults нажатием «- триггер».Этот триггер предотвратит мигание кнопки.Если вам просто нужен 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 для Visual Studio для редактирования шаблона элемента, который вы хотите изменить.Для этой кнопки просто удалите триггер IsDefaults.Вот обновленный фрагмент кода.

<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>
9 голосов
/ 14 марта 2011

Простое решение: установите для кнопки «Фокусируемый» значение «Ложь».

5 голосов
/ 11 мая 2011

Немного менее навязчивым способом устранения этого мигания будет установка нового ControlTemplate для ButtonBase с удаленными ошибочными привязками.

Я взял это через StyleSnooper из стиля кнопок по умолчанию и обновил / упростил до стиля для ButtonBase, который просто предоставляет новый ControlTemplate *.Для этого добавьте ссылку на сборку в Presentation.Aero и введите пространство имен Microsoft.Windows.Themes в свой ResourceDictionary.

Здесь я специально убрал способность уязвимой кнопки «мигать».на свойстве IsDefault путем жесткого кодирования RenderDefaulted в false;Вы, вероятно, также захотите заменить 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>

Затем используйте этот стиль как BasedOn для своей кнопки:

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

(*) И да, мыдолжно действительно иметь возможность использовать BasedOn для ControlTemplates ...

1 голос
/ 20 октября 2010

Я с тех пор, как мой первый ответ столкнулся с этой проблемой при прикреплении изображений к кнопкам, и я решил, установив изображение и кнопку растягивать и используя размер на границе, это решило проблему.

Пример кода ..

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