2010-10-20 58 views
13

Mi aplicación WPF tiene un administrador de estilos que he creado en blend.Botón parpadeante en la aplicación WPF

Mi problema es este: tengo un botón de inicio de sesión que parpadea ocasionalmente y no puedo encontrar la manera de eliminar este comportamiento.

Aquí está el código de estilo para mi caja de entrada:

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

Y aquí es mi código de la ventana:

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

El botón que estoy hablando se llama "LoginBtn", como es su estilo

¿Cómo puedo eliminar ese comportamiento de parpadeo? Gracias por adelantado.

+0

@ user481711: cámbialo a C# – yadab

+0

¿Puedes definir mejor "blink"? ¿Quiere decir que cambia constantemente entre dos estados visuales, o se desencadena por algo como el desplazamiento del mouse? – Val

Respuesta

1

Desde mi primera respuesta me encontré con este problema al adjuntar imágenes a los botones y me di cuenta al configurar la imagen y el botón para estirar y utilizando un tamaño en el borde que solucionó el problema.

Código de ejemplo ..

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

Eso es intermitente debido al estilo por defecto que utiliza WPF para los botones. Para ser más específico, se debe al desencadenador en la plantilla de control del botón. Para eliminar esto, vaya a blend, haga clic derecho en el botón y seleccione "Editar plantilla" -> "Editar una copia". Haga clic en el elemento secundario del presentador de contenido (de forma predeterminada, este es el control llamado "Chrome"). Luego, en la pestaña disparadores, RenderDefaulted inactivo presionando "- gatillo". Ese disparador evitará que el botón parpadee. Si lo que desea es el XAML para todo eso, aquí está envuelto por 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> 

Entonces, dondequiera que el botón es, aplicar este estilo ...

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

Actualización: El estilo de botón predeterminado ha cambiado a lo largo de los años. La idea es la misma, use Blend for Visual Studio para editar el templete del elemento que desea cambiar. Para este botón, simplemente elimine el desencadenador IsDefaulted en primer lugar. Aquí hay un fragmento de código actualizado.

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

Funciona como un encanto. Gracias por describir que podemos hacer clic derecho y editar una copia de una plantilla, es extremadamente útil. – MasterMastic

+0

no funciona, no tengo ningún elemento secundario para el presentador de contenido, y no tiene "chrome" o "RenderDefaulted". –

+0

Parece que las cosas han cambiado desde 2011. Ya no hay Microsoft_Windows_Themes: ButtonChrome control. Ahora puede eliminar el desencadenador IsDefaulted por completo. Actualizaré mi respuesta para reflejar los cambios. – Onosa

9

Solución simple: Establezca el botón "Enfocable" en False.

+12

Eso abrirá una lata de gusanos tan pronto como estés lidiando con la navegación por el teclado ... – Jan

+3

Es más como cortarte la cabeza si tienes dolor de cabeza. – Marshal

5

Una forma un poco menos molesto de eliminar el parpadeo que sería estableció un nuevo ControlTemplate para ButtonBase con los enlaces ofensivos retirados.

Tomé esto a través de StyleSnooper desde el Estilo por defecto del Botón y lo actualicé/simplifiqué para que sea un Estilo para ButtonBase que simplemente proporciona un nuevo ControlTemplate *. Para ello, agregue una referencia de ensamblado a Presentation.Aero e introduzca el espacio de nombres Microsoft.Windows.Themes en ResourceDictionary.

Aquí, eliminé específicamente la capacidad del botón afectado de "parpadear" en su propiedad IsDefault al codificar RenderDefaulted como falso; probablemente también desee reemplazar 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> 

A continuación, utilice este estilo como BasedOn para su botón:

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

(*) Y sí, que realmente debería tener la capacidad de utilizar BasedOn para ControlTemplates así ...