SharpVectors icon indicating copy to clipboard operation
SharpVectors copied to clipboard

Change svg fill and brush colour via binding

Open stojy opened this issue 4 years ago • 6 comments

A useful feature would be to allow the color defined in the svg to be overridden from a xaml binding (or indeed code behind).

Some use cases that come to mind..

  • Support 'hover over' color changing effect, e.g. allow a binding to be created to change the color when during a mouse over event.
  • Support theming, e.g. allow a dark theme to override the default svg color
  • Support 'off the shelf' svg libraries, e.g. allow a quick way to change a monotone svg (typically black) to something more useful without having to edit the svg.

AFAIK, it's been discussed elsewhere, e.g. #163, #88.

The following code snippet (heavily based on https://github.com/ElinamLLC/SharpVectors/issues/88#issuecomment-576503027) integrated into SvgViewbox would provide the functionality to override the 'fill' and 'stroke' brushes. It would need a bit of improvement though to remove the default color brushes mind you.

    public class SvgViewboxEx : SvgViewbox
    {
        public static readonly DependencyProperty FillProperty = DependencyProperty.Register("Fill", typeof(Brush), typeof(SvgViewboxEx), new PropertyMetadata(Brushes.BlueViolet));

        public static readonly DependencyProperty StrokeProperty = DependencyProperty.Register("Stroke", typeof(Brush), typeof(SvgViewboxEx), new PropertyMetadata(Brushes.DarkViolet));

        public Brush Fill
        {
            get => (Brush) GetValue(FillProperty);
            set => SetValue(FillProperty, value);
        }

        public Brush Stroke
        {
            get => (Brush) GetValue(StrokeProperty);
            set => SetValue(StrokeProperty, value);
        }

        protected override void OnSettingsChanged()
        {
            base.OnSettingsChanged();

            var drawings = ((SvgDrawingCanvas) Child).DrawObjects;

            foreach (var drawing in drawings)
            {
                if (drawing is GeometryDrawing geometryDrawing)
                {
                    // svg fill color - translated to a geometry.Brush
                    var brush = new Binding(nameof(Fill))
                                    {
                                        Source = this,
                                        Mode = BindingMode.OneWay
                                    };
                    BindingOperations.SetBinding(geometryDrawing, GeometryDrawing.BrushProperty, brush);

                    // svg stroke color - translated to a geometry.Pen.Brush
                    if (geometryDrawing.Pen != null)
                    {
                        var stroke = new Binding(nameof(Stroke))
                                         {
                                             Source = this,
                                             Mode = BindingMode.OneWay
                                         };
                        BindingOperations.SetBinding(geometryDrawing.Pen, Pen.BrushProperty, stroke);
                    }
                }
            }
        }
    }

At any rate, the above code can be used verbatim for anyone wanting this feature without waiting for an equivalent in SharpVectors.

stojy avatar May 25 '21 13:05 stojy

@stojy Sorry for the delay. SvgIcon is now added to support this feature. It is derived from the WPF Image control. For users requiring more than monochrome features SvgIcon, the base class SvgBitmap is provided and can be extended.

NOTE: I cannot find any case to bind to the pen/stroke, even thought it is supported in SvgIcon. If you have any real world example, please post a sample.

paulushub avatar Jul 19 '22 10:07 paulushub

@paulushub, don't mean to rush, but do we know when the nuget package that includes this feature will be released?

r-tmp avatar Sep 04 '22 20:09 r-tmp

@r-tmp Thanks for the interest. Unfortunately, there is still no feedback on this feature. If you find it useful, please test it and provide some feedbacks, that will make it easy to release.

paulushub avatar Sep 06 '22 02:09 paulushub

@paulushub Just tested it in a small project (.NET 6), not much to say except that seems to be working as expected 🙂.

r-tmp avatar Sep 06 '22 21:09 r-tmp

Thanks a lot, I spent like an hour searching for a solution to change the color of my complete black SVG.

You need a reallife example? - Most SVGs are icons used in WPF views. Almost all icons are solid color, most black, unless multicolor icons, but that's a different story.

However, this code works like a charm, and I hope for a integration in the next version.

And maybe someday, multicolor svg icon support, that means, every closed element of a SVG curve can be filled with a different color. e.g. Array of elements with the option to fill each one independently.

spreedated avatar Sep 30 '22 19:09 spreedated

Thanks for the feedback.

And maybe someday, multicolor svg icon support, that means, every closed element of a SVG curve can be filled with a different color. e.g. Array of elements with the option to fill each one independently.

Will need more information on this, please write more on this if you have the time.

paulushub avatar Sep 30 '22 19:09 paulushub

Sorry for the delay, release 1.8.1 is now available.

paulushub avatar Oct 24 '22 09:10 paulushub