2009-05-25 10 views
5

¿Hay alguna manera de crear un tipo de "cepillo de colores sólido" que sea una mezcla de 2 cepillos de color sólido?Cepillo combinado de color sólido

Para el color de fondo, me gustaría poder utilizar una DynamicReference para otro cepillo. Mientras que el otro color (en la parte frontal) podría ser un color estático con opacidad.

Siéntase libre de pedir aclaraciones si esto realmente no hace sentido!

Respuesta

4

Desafortunadamente, pinceles personalizados no se admiten en WPF (los tipos de cepillo están marcados 'interno' y no pueden ser heredados de), por lo que la creación de un cepillo que es una mezcla de dos Los pinceles que se pueden usar desde XAML como un SolidColorBrush normal no son posibles.

Como solución alternativa, puede usar una MarkupExtension para simular el comportamiento de un pincel personalizado, que le permite usar la sintaxis XAML y proporcionar un valor personalizado, que nos permite usar el SolidColorBrush incorporado (no es necesario pincel personalizado)) establecida en el valor que se obtiene al mezclar dos colores:

/// <summary> 
/// Markup extension to mix two SolidColorBrushes together to produce a new SolidColorBrush. 
/// </summary> 
[MarkupExtensionReturnType(typeof(SolidColorBrush))] 
public class MixedColorBrush : MarkupExtension, INotifyPropertyChanged 
{ 
    /// <summary> 
    /// The foreground mix color; defaults to white. 
    /// If not changed, the result will always be white. 
    /// </summary> 
    private SolidColorBrush foreground = Brushes.White; 

    /// <summary> 
    /// The background mix color; defaults to black. 
    /// If not set, the result will be the foreground color. 
    /// </summary> 
    private SolidColorBrush background = Brushes.Black; 

    /// <summary> 
    /// PropertyChanged event for WPF binding. 
    /// </summary> 
    public event PropertyChangedEventHandler PropertyChanged; 

    /// <summary> 
    /// Gets or sets the foreground mix color. 
    /// </summary> 
    public SolidColorBrush Foreground 
    { 
     get 
     { 
      return this.foreground; 
     } 
     set 
     { 
      this.foreground = value; 
      this.NotifyPropertyChanged("Foreground"); 
     } 
    } 

    /// <summary> 
    /// Gets or sets the background mix color. 
    /// </summary> 
    public SolidColorBrush Background 
    { 
     get 
     { 
      return this.background; 
     } 
     set 
     { 
      this.background = value; 
      this.NotifyPropertyChanged("Background"); 
     } 
    } 

    /// <summary> 
    /// Returns a SolidColorBrush that is set as the value of the 
    /// target property for this markup extension. 
    /// </summary> 
    /// <param name="serviceProvider">Object that can provide services for the markup extension.</param> 
    /// <returns>The object value to set on the property where the extension is applied.</returns> 
    public override object ProvideValue(IServiceProvider serviceProvider) 
    { 
     if (this.foreground != null && this.background != null) 
     { 
      // Create a new brush as a composite of the old ones 
      // This does simple non-perceptual additive color, e.g 
      // blue + red = magenta, but you can swap in a different 
      // algorithm to do subtractive color (red + yellow = orange) 
      return new SolidColorBrush(this.foreground.Color + this.background.Color); 
     } 

     // If either of the brushes was set to null, return an empty (white) brush. 
     return new SolidColorBrush(); 
    } 

    /// <summary> 
    /// Raise the property changed event. 
    /// </summary> 
    /// <param name="propertyName">Name of the property which has changed.</param> 
    protected void NotifyPropertyChanged(string propertyName) 
    { 
     if (this.PropertyChanged != null) 
     { 
      this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 
} 

que luego se pueden utilizar desde XAML como lo haría con un cepillo normal:

<Grid> 
    <Grid.Background> 
     <local:MixedColorBrush Foreground="Blue" Background="Red"/> 
    </Grid.Background> 
</Grid> 

o utilizando la sintaxis de extensión de marcado:

<Grid Background="{local:MixedColorBrush Foreground=Blue, Background=Red}"> 

La desventaja de este enfoque es que no puede usar las referencias de DynamicResource o StaticResource para vincular los valores a otros recursos en su aplicación. MarkupExtension no es DependencyObject, y el enlace de recursos solo funciona en DependencyObjects; los Pinceles integrados son DependencyObjects, por lo que el enlace funciona con pinceles tradicionales.

3

Obtenga los colores de los pinceles de primer plano y de fondo, mézclelos y cree un nuevo pincel del color resultante.

Ejemplo en C#:

Color foreground = foregroundBrush.Color; 
Color background = backgroundBrush.Color; 

int opacity = 25; 

int r = (opacity * (foreground.R - background.R)/100) + background.R; 
int g = (opacity * (foreground.G - background.G)/100) + background.G; 
int b = (opacity * (foreground.B - background.B)/100) + background.B; 

SolidColorBrush mixedBrush = new SolidColorBrush(Color.FromArgb(r, g, b)); 
+0

Buen ejemplo ...pero esperaba la versión XAML de esto ... – Entrodus

6

Me encontré con el mismo problema. Normalmente solo uso una xaml para las sombras oscuras básicas, las luces básicas y luego una para cada acento de color (azul, rojo, etc.). El acento se ve ligeramente, lo que lo hace más oscuro cuando se selecciona el tema más oscuro con un fondo más oscuro.

Al crear un tema con un color de acento secundario para tener más contraste en la aplicación (por ejemplo gris cuando se selecciona tema claro, color de acento cuando el tema es oscuro), necesitaba construir un pincel de dos colores, de lo contrario Tendría que crear un tema oscuro y claro para cada color.

Esto es lo que yo uso:

<DrawingBrush x:Key="SecondaryAccentColorBrush" Viewport="0,0,1,1" TileMode="Tile"> 
    <DrawingBrush.Drawing> 
     <DrawingGroup> 
      <GeometryDrawing> 
       <GeometryDrawing.Geometry> 
        <RectangleGeometry Rect="0,0,1,1" /> 
       </GeometryDrawing.Geometry> 
       <GeometryDrawing.Brush> 
        <SolidColorBrush Color="{DynamicResource AccentColor}"/> 
       </GeometryDrawing.Brush> 
      </GeometryDrawing> 
      <GeometryDrawing> 
       <GeometryDrawing.Geometry> 
        <RectangleGeometry Rect="0,0,1,1" /> 
       </GeometryDrawing.Geometry> 
       <GeometryDrawing.Brush> 
        <SolidColorBrush Color="{DynamicResource Gray10}"/> 
       </GeometryDrawing.Brush> 
      </GeometryDrawing> 
     </DrawingGroup> 
    </DrawingBrush.Drawing> 
</DrawingBrush> 

Cuando se cambia el tema, el alfa de interruptores "Gray10" entre 00 y FF, por lo tanto el cepillo muestra gris o el color de acento.

3

Una forma fácil de hacerlo (pero probablemente no optimizado), crear un LinearGradientBrush de los dos colores en el modo de repetición con el punto extremo es igual al punto de inicio:

<LinearGradientBrush SpreadMethod="Repeat" EndPoint="0,0"> 
           <GradientStop Color="Red" Offset="0" /> 
           <GradientStop Color="Yellow" Offset="1" /> 
          </LinearGradientBrush> 

Ésta le da un cepillo de naranja.

Cuestiones relacionadas