user856197
user856197

Reputation:

XAML SVG color change at runtime

We have a set of SVGs stored within a resource dictionary.

Example:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <DrawingImage x:Key="Bell">
        <DrawingImage.Drawing>
            <DrawingGroup Opacity="1">
                <DrawingGroup.Children>
                    <DrawingGroup Opacity="1">
                        <DrawingGroup.Children>
                            <DrawingGroup Opacity="1">
                                <DrawingGroup.Children>
                                    <GeometryDrawing Brush="#FF000000" Pen="{x:Null}">
                                        <GeometryDrawing.Geometry>
                                            <PathGeometry FillRule="Nonzero" Figures="........." />
                                        </GeometryDrawing.Geometry>
                                    </GeometryDrawing>
                                </DrawingGroup.Children>
                            </DrawingGroup>
                        </DrawingGroup.Children>
                    </DrawingGroup>
                </DrawingGroup.Children>
            </DrawingGroup>
        </DrawingImage.Drawing>
    </DrawingImage>
</ResourceDictionary>

If you noticed the GeometryDrawing Brush is set to #ff000000 (black). The problem we face is allowing a view to display this SVG and assign the color at runtime (via binding)

Our Window (view) has the Resource Dictionary with the icons inside of the Window.Resources.

We are looking for a solution like so:

<Image Source="{StaticResource Bell}" Fill="#FF884422"/>

Upvotes: 4

Views: 9478

Answers (4)

Brandon Hood
Brandon Hood

Reputation: 328

By building on top of Paolo's non-working answer, I was able to solve this.

The "MyImage" class:

Public Class MyImage
    Inherits System.Windows.Controls.Image

    Public Property Color As System.Windows.Media.SolidColorBrush

End Class

Inside the resource dictionary, assign the DrawingImage to the Source setter of a MyImage style:

<Style TargetType="{x:Type local:MyImage}" x:Key="Bell">
        <Setter Property="Source">
            <Setter.Value>
                <DrawingImage>
                    <DrawingImage.Drawing>
                        <DrawingGroup Opacity="1">
                            <DrawingGroup.Children>
                                <DrawingGroup Opacity="1">
                                    <DrawingGroup.Children>
                                        <DrawingGroup Opacity="1">
                                            <DrawingGroup.Children>
                                                <GeometryDrawing
                                                    Brush="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type local:MyImage}}, Path=Color}"
                                                    Pen="{x:Null}" />
                                            </DrawingGroup.Children>
                                        </DrawingGroup>
                                    </DrawingGroup.Children>
                                </DrawingGroup>
                            </DrawingGroup.Children>
                        </DrawingGroup>
                    </DrawingImage.Drawing>
                </DrawingImage>
            </Setter.Value>
        </Setter>
</Style>

Inside the window's XAML file:

<Window
    ...
    xmlns:local="clr-namespace:AppNameHere">
    <Window.Resources>
        <ResourceDictionary Source="DictionaryName.xaml" />
    </Window.Resources>
    ....
    <Grid Background="Black">
        <local:MyImage Color="Chartreuse" Width="30" Height="30" Style="{StaticResource Bell}" />
    </Grid>
    ...
</Window>

Here's the result: https://i.sstatic.net/7JNyH.png

Upvotes: 2

BerndK
BerndK

Reputation: 1090

Have a look at this tool: https://github.com/BerndK/SvgToXaml

It can convert all svg's automatically to one xaml. The colors are separated and can be set for all images at once or just for a single image. Sample code for changing colors during runtime is included.

The tool is also a svg browser, viewer ...

Upvotes: 4

MHollis
MHollis

Reputation: 1459

The DrawingImage will receive the same datacontext as the window, so you can bind the color to a property on the window's view model.

Dictionary1.xaml

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <DrawingImage x:Key="Bell">
        <DrawingImage.Drawing>
            <DrawingGroup Opacity="1">
                <DrawingGroup.Children>
                    <DrawingGroup Opacity="1">
                        <DrawingGroup.Children>
                            <DrawingGroup Opacity="1">
                                <DrawingGroup.Children>
                                    <GeometryDrawing Brush="{Binding IconColor}" Pen="{x:Null}">
                                        <GeometryDrawing.Geometry>
                                            <PathGeometry FillRule="Nonzero" Figures="........." />
                                        </GeometryDrawing.Geometry>
                                    </GeometryDrawing>
                                </DrawingGroup.Children>
                            </DrawingGroup>
                        </DrawingGroup.Children>
                    </DrawingGroup>
                </DrawingGroup.Children>
            </DrawingGroup>
        </DrawingImage.Drawing>
    </DrawingImage>
</ResourceDictionary>

MyTestWindow.xaml

<Window x:Class="MyTestWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">        
    <Window.Resources>
        <ResourceDictionary Source="Dictionary1.xaml" />
    </Window.Resources>
    <Grid>
        <Image Source="{StaticResource Bell}" />
    </Grid>
</Window>

Then the view model will need an IconColor property.

Upvotes: 0

Paolo Trentarose
Paolo Trentarose

Reputation: 11

<Window x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WpfApplication1"
    Title="MainWindow" Height="350" Width="525" >
<Window.Resources>
    <DrawingImage x:Key="Bell1">
        <DrawingImage.Drawing>
            <DrawingGroup Opacity="1">
                <DrawingGroup Opacity="1">
                    <DrawingGroup Opacity="1">
                        <GeometryDrawing  Brush="{Binding Color}" Pen="{x:Null}">
                            <GeometryDrawing.Geometry>
                                <PathGeometry FillRule="Nonzero"  Figures="M 10,100 C 10,300 300,-200 300,100" />
                            </GeometryDrawing.Geometry>
                        </GeometryDrawing>
                    </DrawingGroup>
                </DrawingGroup>
            </DrawingGroup>
        </DrawingImage.Drawing>
    </DrawingImage>
</Window.Resources>
<Grid>
    <local:MyImage DataContext="{Binding ElementName=myImage, Mode=OneWay}" x:Name="myImage"  Color="Red" Source="{StaticResource Bell1}" ></local:MyImage>

</Grid>

Upvotes: 1

Related Questions