Изменение цвета XAML SVG во время выполнения

У нас есть набор SVG, хранящихся в словаре ресурсов.

Пример:

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

Если вы заметили, для кисти GeometryDrawing задан цвет #ff000000 (черный). Проблема, с которой мы сталкиваемся, заключается в том, чтобы позволить представлению отображать этот SVG и назначать цвет во время выполнения (через привязку).

Наше окно (представление) имеет словарь ресурсов со значками внутри Window.Resources.

Мы ищем такое решение:

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

person Sean Hobbs    schedule 08.04.2015    source источник
comment
Это кажется чепухой, лично я просто экспортирую их как XAML и превращаю в шаблоны ContentControl. где я могу передать все эти вещи в качестве свойств зависимостей дочерним элементам в одном лайнере и сохранить шаблоны в словаре ресурсов.   -  person Chris W.    schedule 08.04.2015
comment
Это похоже на путь, по которому я собираюсь пойти. У вас есть пример, которым вы можете поделиться?   -  person Sean Hobbs    schedule 09.04.2015
comment
Да, у меня встречи начинаются через минуту, но я вернусь к этому после обеда и свяжу вас, как только появится минутка.   -  person Chris W.    schedule 09.04.2015
comment
Спасибо! Вы человек!   -  person Sean Hobbs    schedule 09.04.2015
comment
Крис, что ты вкладываешь в свои шаблоны? PathGeometry или просто значения Path?   -  person Sean Hobbs    schedule 09.04.2015
comment
Вы можете кидать туда все, что хотите, я забыл, что ответил на аналогичный вопрос здесь, чтобы у вас была ссылка, затем вы можете установить сеттеры для свойств зависимостей, которые вы хотите использовать в шаблоне, если вы используете {TemplateBinding blah}, что позволит вам сделать что-то вроде ‹ContentControl Fill=Red Stroke=Blue/› и т. д. и т. д.   -  person Chris W.    schedule 09.04.2015
comment
Из-за ограничений комментариев я должен разбить свой ответ на несколько ответов. Я попробовал следующее (удалил часть xaml), но {TemplateBinding Background}. Не работает.   -  person Sean Hobbs    schedule 09.04.2015
comment
‹Style x:Key=SomeStyle TargetType=ContentControl› ‹Setter Property=Template› ‹Setter.Value› ‹ControlTemplate TargetType=ContentControl› ‹Image› ‹Image.Source› ‹DrawingImage› .... ‹GeometryDrawing Brush={TemplateBinding Background }/› .... ‹/DrawingImage› ‹/Image.Source› ‹/Image› ‹/ControlTemplate› ‹/Setter.Value› ‹/Setter› ‹/Style›   -  person Sean Hobbs    schedule 09.04.2015
comment
Как вы добавляете новые свойства зависимостей в элемент управления содержимым? Вы создаете собственный элемент управления контентом, который наследует и добавляет новые свойства? Что делать, если я хочу привязать к этому значку несколько цветов?   -  person Sean Hobbs    schedule 09.04.2015
comment
Давайте продолжим обсуждение в чате.   -  person Sean Hobbs    schedule 09.04.2015
comment
Понял, можете удалять, я вам на почту пришлю то, что написал в чате.   -  person Sean Hobbs    schedule 09.04.2015


Ответы (3)


Опираясь на нерабочий ответ Паоло, я смог решить эту проблему.

Класс MyImage:

Public Class MyImage
    Inherits System.Windows.Controls.Image

    Public Property Color As System.Windows.Media.SolidColorBrush

End Class

Внутри словаря ресурсов назначьте DrawingImage установщику Source стиля MyImage:

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

Внутри XAML-файла окна:

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

Вот результат: https://i.stack.imgur.com/7JNyH.png

person Brandon Hood    schedule 10.04.2015

Взгляните на этот инструмент: https://github.com/BerndK/SvgToXaml

Он может автоматически конвертировать все svg в один xaml. Цвета разделены и могут быть установлены для всех изображений сразу или только для одного изображения. Пример кода для изменения цветов во время выполнения включен.

Инструмент также является браузером svg, просмотрщиком ...

person BerndK    schedule 07.05.2015
comment
@Joseph: библиотека предназначена для преобразования SVG в объект Path .NET. Этот по дизайну не цветной, поэтому вы можете (и должны) установить цвет, который вам нравится. Это хорошо для одноцветных значков, используемых в современном дизайне. Если вам нужны многоцветные значки, вы можете объединить несколько путей (как показано в демонстрации SvgToXaml), но я бы подумал об использовании файлов png. При этом вы можете потерять преимущество путей/геометрий: масштабируемость без потери качества. - person BerndK; 22.06.2020

DrawingImage получит тот же контекст данных, что и окно, поэтому вы можете привязать цвет к свойству модели представления окна.

Словарь1.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>

Затем модели представления потребуется свойство IconColor.

person MHollis    schedule 08.04.2015