2010-12-29 24 views
10

Seguí ChrisFhere y escribo un simple demo.Cómo eliminar el borde de ButtonChrome (al definir la plantilla de un borde)?

... abrir su proyecto en Expression Blend, seleccione el botón derecho y haga clic en y seleccione "Editar plantilla> Editar una copia ..". Esto copia la plantilla existente en una que puede modificar. Es más fácil si lo crea en un diccionario de recursos .

Y puedo ver la plantilla de-la-pantalla detrás del botón de la siguiente captura de pantalla (El ButtonChrome en Recursos).

Quiero eliminar el borde blanco gradiente de la ButtonChromeY mantener todo lo demás de la interfaz de usuario del botón permanezca como está. ¿Cómo puedo hacer eso?

ps. Para simplificar el problema, uso ButtonChrome como control normal en mi vista. Miro las propiedades pero aún NO tengo idea de dónde eliminar el borde "blanco".

(El ButtonChrome en uso) alt text

(El ButtonChrome en Recursos) alt text

Respuesta

10

No creo que hay una manera fácil de deshacerse de esa frontera blanca. La rutina real que se llama es DrawInnerBorder y se llama desde dentro de OnRender en ButtonChrome.

protected override void OnRender(DrawingContext drawingContext) 
{ 
    Rect bounds = new Rect(0.0, 0.0, base.ActualWidth, base.ActualHeight); 
    this.DrawBackground(drawingContext, ref bounds); 
    this.DrawDropShadows(drawingContext, ref bounds); 
    this.DrawBorder(drawingContext, ref bounds); 

    // This one draws the white Rectangle 
    this.DrawInnerBorder(drawingContext, ref bounds); 
} 

private void DrawInnerBorder(DrawingContext dc, ref Rect bounds) 
{ 
    if ((base.IsEnabled || this.RoundCorners) && ((bounds.Width >= 4.0) && (bounds.Height >= 4.0))) 
    { 
     Pen innerBorderPen = this.InnerBorderPen; 
     if (innerBorderPen != null) 
     { 
      dc.DrawRoundedRectangle(null, innerBorderPen, new Rect(bounds.Left + 1.5, bounds.Top + 1.5, bounds.Width - 3.0, bounds.Height - 3.0), 1.75, 1.75); 
     } 
    } 
} 

Como podemos ver, no hay ninguna propiedad para desactivar esta. Puede verificarlo configurando IsEnabled="False" y RoundCorners="False" en ButtonChrome o estableciendo Ancho o Alto a algo así como 3.99 y el "Borde blanco" desaparece.

actualización
Para deshabilitar el borde interior del ButtonChrome puede crear su propio ButtonChrome que añade esta propiedad. Desafortunadamente ButtonChrome está sellado por lo que no podemos heredar de él. Traté de copiar toda la clase y agregar la propiedad DisableInnerBorder y parece estar funcionando.Se puede utilizar de esta manera

<local:MyButtonChrome ... 
         DisableInnerBorder="True"> 

Aparte de eso, funciona igual que el ButtonChrome regular y también se pueden añadir otras propiedades, etc., que es posible que desee. Puede haber inconvenientes en este método que no he pensado, pero para una pequeña prueba funcionó bien.

Apperently 937 líneas de código era demasiado poder escribir en el SO :) Me subido MyButtonChrome.cs aquí: http://www.mediafire.com/?wnra4qj4qt07wn6

+0

¿Cómo puede obtener estos códigos? Me sorprende :) –

+0

@Nam Gi VU: utilicé .NET Reflector y agregué el ensamblado PresentationFramework.Aero para depurar. Luego, pasé por las rutinas de dibujo para ver dónde se dibujaba esto y verifiqué si había alguna manera de desactivarlo :) –

+0

Gracias Meleak! Acerca de su sugerencia de usar 'Border' en lugar de' ButtonChrome', voy a perder todo el efecto UI de un botón normal (el mouse sobre, presionado, etc.) ¿Tiene alguna solución para eso? –

4

Usted no debe tratar de personalizar ButtonChrome. * Las clases de Chrome son específicas de un tema, es decir, contienen la implementación de un tema de Windows específico y no puede anularlo. Observe la declaración del espacio de nombres "Microsoft_Windows_Themes" en su diccionario de recursos: probablemente contenga algo como PresentationFramework.Aero ...

Lo que debe hacer en sus plantillas personalizadas es utilizar el borde habitual en lugar de ButtonChrome y definir desencadenantes que lo harán cambie su fondo, etc. cuando se presiona o se pasa el botón.

Aquí se muestra un ejemplo:

<Style x:Key="BaseButtonStyle" 
    TargetType="{x:Type ButtonBase}"> 
<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="{StaticResource ButtonNormalForeground}" /> 
<Setter Property="HorizontalContentAlignment" 
     Value="Center" /> 
<Setter Property="VerticalContentAlignment" 
     Value="Center" /> 
<Setter Property="Padding" 
     Value="5,2,5,2" /> 
<Setter Property="Template"> 
    <Setter.Value> 
     <ControlTemplate TargetType="{x:Type ButtonBase}"> 
      <Border Name="Chrome" 
        Background="{TemplateBinding Background}" 
        BorderBrush="{TemplateBinding BorderBrush}" 
        BorderThickness="{TemplateBinding BorderThickness}" 
        SnapsToDevicePixels="true" 
        CornerRadius="2"> 
       <ContentPresenter Margin="{TemplateBinding Padding}" 
            VerticalAlignment="{TemplateBinding VerticalContentAlignment}" 
            HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" 
            RecognizesAccessKey="True" 
            SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" /> 
      </Border> 
      <ControlTemplate.Triggers> 
       <Trigger Property="IsMouseOver" 
         Value="True"> 
        <Setter Property="Background" 
          Value="{StaticResource ButtonHoverBackground}" /> 
        <Setter Property="Foreground" 
          Value="{StaticResource ButtonHoverForeground}" /> 
       </Trigger> 

       <Trigger Property="IsPressed" 
         Value="True"> 
        <Setter Property="Background" 
          Value="{StaticResource ButtonPressedBackground}" /> 
        <Setter Property="Foreground" 
          Value="{StaticResource ButtonPressedForeground}" /> 
       </Trigger> 
       <Trigger Property="ToggleButton.IsChecked" 
         Value="True"> 
        <Setter Property="Background" 
          Value="{StaticResource ButtonHoverBackground}" /> 
        <Setter Property="Foreground" 
          Value="{StaticResource ButtonNormalForeground}" /> 
       </Trigger> 
       <Trigger Property="IsEnabled" 
         Value="false"> 
        <Setter Property="Foreground" 
          Value="#ADADAD" /> 
       </Trigger> 
      </ControlTemplate.Triggers> 
     </ControlTemplate> 
    </Setter.Value> 
</Setter> 

+0

¿Puede darme una plantilla completa que ayude a mantener toda la característica de IU de un botón excepto el "borde blanco"? –

0

si se quiere evitar la WhiteBorder solo tienes que acaba de cambiar el BorderBrush = Transparente

<Microsoft_Windows_Themes:ButtonChrome x:Name="Chrome" SnapsToDevicePixels="true" 
         Background="{TemplateBinding Background}" BorderBrush="Transparent" 
         RenderDefaulted="{TemplateBinding IsDefaulted}" RenderMouseOver="{TemplateBinding IsMouseOver}" 
          RenderPressed="{TemplateBinding IsPressed}"> 
          <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" RecognizesAccessKey="True"/> 
         </Microsoft_Windows_Themes:ButtonChrome> 

Si desea modificar algunas otras cosas que tienen que crear su propia ControlTemplate

favor este enlace

http://mark-dot-net.blogspot.com/2007/07/creating-custom-wpf-button-template-in.html

aquí tienen diferentes plantillas de botones

+0

@Kumar: ¿Has probado tu sugerencia? No funciona –

16

Una de las grandes fetatures de WPF es la capacidad de aprovechar el comportamiento de un control, mientras que el canje por completo el aspecto de que control.You puede simplemente eliminar el cromo en conjunto y crea una apariencia personalizada que coincida con tu requerimiento.

Muestra

<Style x:Key="NoChromeButton" TargetType="{x:Type Button}"> 
     <Setter Property="Background" Value="Transparent"/> 
     <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}"> 
        <Grid x:Name="Chrome" Background="{TemplateBinding Background}" SnapsToDevicePixels="true"> 
         <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/> 
        </Grid> 
        <ControlTemplate.Triggers> 
         <Trigger Property="IsEnabled" Value="false"> 
          <Setter Property="Foreground" Value="#ADADAD"/> 
          <Setter Property="Opacity" TargetName="Chrome" Value="0.5"/> 
         </Trigger> 
        </ControlTemplate.Triggers> 
       </ControlTemplate> 
      </Setter.Value> 
     </Setter> 
    </Style> 

comprobarlo, también http://www.designerwpf.com/2008/03/27/wpf-designers-guide-to-styles-and-templates/

Este enlace parece funcionar ahora: http://www.designersilverlight.com/2008/03/27/wpf-designers-guide-to-styles-and-templates/

+0

¡Muchísimas gracias! –

0

Asfter discutir con Meleak por un tiempo, finalmente conseguí la solución final para mi pregunta! Gracias Meleak!

Puede descargar el solution source codes here.

1

Me doy cuenta de que este es un hilo antiguo, pero lo encontré cuando intentaba hacer lo mismo y no encontré ninguna solución excelente. Pensé en publicar lo que se me ocurrió en caso de que ayude a alguien más.

Lo que quería eran botones planos que usaran el cromo normal cuando pasaban por encima. La mejor manera que pude de hacer esto fue hacer trampa y usar dos ContentPresenters dentro de una Grilla con dos filas. Un presentador de contenido está dentro del ButtonChrome normal y uno está dentro de un borde. Solo se muestra una fila de grillas a la vez y el colocador en el desencadenante IsMouseOver determina cuál se muestra.

<Window.Resources> 
    <Style x:Key="ButtonFocusVisual"> 
     <Setter Property="Control.Template"> 
      <Setter.Value> 
       <ControlTemplate> 
        <Rectangle StrokeDashArray="1 2" StrokeThickness="1" Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" SnapsToDevicePixels="true" Margin="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="Transparent"/> 
    <Style x:Key="ActionButtonStyle" TargetType="{x:Type Button}"> 
     <Setter Property="FocusVisualStyle" Value="{StaticResource ButtonFocusVisual}"/> 
     <Setter Property="Background" Value="{x:Null}"/> 
     <Setter Property="BorderBrush" Value="{x:Null}"/> 
     <Setter Property="BorderThickness" Value="0"/> 
     <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}"> 
        <Grid> 
         <Grid.RowDefinitions> 
          <RowDefinition x:Name="ContentWithChrome" Height="0"></RowDefinition> 
          <RowDefinition x:Name="ContentWithBorder" Height="Auto"></RowDefinition> 
         </Grid.RowDefinitions> 
         <Themes:ButtonChrome Grid.Row="0" 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}"/> 
         </Themes:ButtonChrome> 
         <Border Grid.Row="1" Margin="0,2,0,2"> 
          <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/> 
         </Border> 
        </Grid> 
        <ControlTemplate.Triggers> 
         <Trigger Property="IsMouseOver" Value="True"> 
          <Setter Property="Height" TargetName="ContentWithChrome" Value="Auto" /> 
          <Setter Property="Height" TargetName="ContentWithBorder" Value="0" /> 
         </Trigger> 
         <Trigger Property="IsKeyboardFocused" Value="true"> 
          <Setter Property="RenderDefaulted" TargetName="Chrome" Value="true"/> 
         </Trigger> 
         <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> 
0

Una opción es utilizar también otra biblioteca como telerik o xceed (también disponible para uso comercial gratuito). En mi solución, creé una clase y la obtuve de Xceed.Wpf.Toolkit.Chromes.ButtonChrome (Microsoft ButtonChrome está sellado). En mi ResourceDictionary implementé un estilo para Combobox, creado por Blend para VS. En el ControlTemplate para el ToggleButton he implementado siguiente código:

<ControlTemplate TargetType="{x:Type ToggleButton}"> 
    <p:ButtonChromeManaged x:Name="Chrome" 
          Width="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}" 
          Background="Transparent" 
          BorderBrush="Transparent" 
          CornerRadius="0" 
          SnapsToDevicePixels="true"> 
     <p:ButtonChromeManaged.Template> 
      <ControlTemplate TargetType="{x:Type p:ButtonChromeManaged}"> 
       <Border Background="Red"> 
        <Path x:Name="Arrow" 
          Margin="0,1,0,0" 
          HorizontalAlignment="Center" 
          VerticalAlignment="Center" 
          Data="{StaticResource DownArrowGeometry}" 
          Fill="Black" /> 
       </Border> 
      </ControlTemplate> 
     </p:ButtonChromeManaged.Template> 

Aquí se puede ver sólo el stuf más impertand. Su DownArrowGeometry y demás, usted sabe que hacer. Espero que esto pueda ayudar a alguien ;-)

Cuestiones relacionadas