Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to bind to an unbindable property without violating MVVM?

I am using SharpVector's SvgViewBox to show static resource images like this:

<svgc:SvgViewbox Source="/Resources/label.svg"/>

which works fine. However, I wish to control what image is shown through a binding to a view model.

The problem I'm experiencing is that the Source property of SvgViewbox is not bindable.

How can I get around this limitation without violating MVVM (e.g., passing the control into the view model and modifying it there)?

like image 465
Lukasz Avatar asked Jan 27 '16 12:01

Lukasz


1 Answers

What you are looking for is called attached properties. MSDN offers a topic on it with the title "Custom Attached Properties"

In your case it may look as simple as this

namespace MyProject.Extensions 
{
    public class SvgViewboxAttachedProperties : DependencyObject
    {
        public static string GetSource(DependencyObject obj)
        {
            return (string) obj.GetValue(SourceProperty);
        }

        public static void SetSource(DependencyObject obj, string value)
        {
            obj.SetValue(SourceProperty, value);
        }

        private static void OnSourceChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            var svgControl = obj as SvgViewbox;
            if (svgControl != null)
            {
                var path = (string)e.NewValue;
                svgControl.Source = string.IsNullOrWhiteSpace(path) ? default(Uri) : new Uri(path);
            }                
        }

        public static readonly DependencyProperty SourceProperty =
            DependencyProperty.RegisterAttached("Source",
                typeof (string), typeof (SvgViewboxAttachedProperties),
                                    // default value: null
                new PropertyMetadata(null, OnSourceChanged));
    }
}

XAML to use it

<SvgViewbox Margin="0 200" 
    local:SvgViewboxAttachedProperties.Source="{Binding Path=ImagePath}" />

Note that local is the namespace prefix and it should point to your assembly/namespace where that class is located at, i.e. xmlns:local="clr-namespace:MyProject.Extensions;assembly=MyProject".

Then only use your attached property (local:Source) and never the Source property.

The new attached property local:Source is of type System.Uri. To update the image first assign null then the filename/filepath again.

like image 200
Tseng Avatar answered Nov 09 '22 19:11

Tseng