2009-05-25 22 views
5

Czy istnieje sposób na stworzenie pewnego rodzaju "solidcolorbrush", który jest mieszanką dwóch pędzli solidcolor?Kombinowany pędzel z jednolitym kolorem

Dla koloru tylnego, chciałbym móc użyć DynamicReference do innego pędzla. Podczas gdy inny kolor (z przodu) może być statycznym kolorem z nieprzezroczystością.

Możesz poprosić o wyjaśnienie, jeśli tak się nie stanie!

Odpowiedz

4

Niestety, niestandardowe szczotki nie są obsługiwane w WPF (Typy szczotek są oznaczone „wewnętrzna” i nie można go odziedziczone), tworząc w ten sposób szczotkę, która jest mieszaniną dwóch Pędzle, które mogą być używane z XAML jak normalny SolidColorBrush, nie są możliwe.

Aby obejść ten problem, można użyć rozszerzenia MarkupExtension do symulacji zachowania niestandardowego pędzla, który umożliwia stosowanie składni XAML i zapewnia niestandardową wartość, co pozwala nam używać wbudowanego narzędzia SolidColorBrush (nie jest wymagana żadna niestandardowa szczotka)) ustawione na wartości można uzyskać podczas mieszania dwóch kolorów:

/// <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)); 
     } 
    } 
} 

które następnie mogą być wykorzystane z XAML jak byś normalnym pędzlem:

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

lub przy użyciu składni rozszerzenie adiustacji:

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

Wadą tego podejścia jest to, że nie można używać odwołań DynamicResource lub StaticResource w celu powiązania wartości z innymi zasobami w aplikacji. MarkupExtension nie jest DependencyObject, a powiązanie zasobów działa tylko na DependencyObjects; wbudowane pędzle to DependencyObjects, dlatego bindowanie działa z tradycyjnymi pędzlami.

3

Uzyskaj kolory z pierwszego planu i pędzli tła, wymieszaj je i utwórz nowy pędzel z uzyskanego koloru.

Przykład 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

Dobry przykład ...ale miałem nadzieję na wersję XAML tego ... – Entrodus

6

Wpadłem na ten sam problem. Zwykle używam tylko jednego xaml dla podstawowych ciemności, podstawowych świateł, a potem jednego dla każdego akcentu kolorystycznego (niebieski, czerwony itp.). Akcent jest lekko przeszywany, co powoduje, że ciemniejszy jest wtedy, gdy wybrano ciemniejszy motyw z ciemniejszym tłem.

Podczas tworzenia motywu z dodatkowym kolorem akcentującym, aby uzyskać większy kontrast w aplikacji (na przykład szare, gdy wybrany jest motyw świetlny, kolor akcentujący, gdy ciemny motyw), musiałem zbudować pędzel z dwóch kolorów, ponieważ w przeciwnym razie musiałby stworzyć ciemny i jasny motyw dla każdego koloru.

Oto co mogę użyć:

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

Kiedy tematem jest włączony, alfa z „Gray10” przełączników pomiędzy 00 i FF, więc szczotka pokazuje albo szary lub kolor akcent.

3

Prostym sposobem, aby to zrobić (ale prawdopodobnie nie zoptymalizowana), stworzyć LinearGradientBrush z dwóch kolorów w trybie powtarzania z Endpoint równa Punkt początkowy:

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

Ten daje szczotki Orange.