0

I have an usercontrol called Header with depenency property IconData:

public Geometry IconData
{
    get { return (Geometry)GetValue(IconDataProperty); }
    set { SetValue(IconDataProperty, value); }
}

public static readonly DependencyProperty IconDataProperty = 
    DependencyProperty.Register(nameof(IconData), typeof(Geometry), typeof(Header), new PropertyMetadata(null);

I have the icon defined in Application

<x:String x:Key="HomeIconGeometry">F1 M 24.0033,56.0078L 24.0033,38.0053L 22.0031,40.0056L 19.0027,35.0049L 38.0053,20.0028L 45.0063,25.5299L 45.0063,21.753L 49.0068,21.0029L 49.0068,28.6882L 57.008,35.0049L 54.0075,40.0056L 52.0073,38.0053L 52.0073,56.0078L 24.0033,56.0078 Z M 38.0053,26.9204L 27.0038,36.005L 27.0038,53.0074L 33.0046,53.0074L 33.0046,42.006L 43.006,42.006L 43.006,53.0074L 49.0068,53.0074L 49.0068,36.005L 38.0053,26.9204 Z</x:String>

And I use it like this:

<local:Header x:Name="HeaderPanel" IconData="{StaticResource HomeIconGeometry}" />

However, the XAML designer sucks as always:

enter image description here

This question is simmilar to PathGeometry in ResourceDictionary with the difference, that the proposed answer does not work in custom controls / usercontrols

Liero
  • 25,216
  • 29
  • 151
  • 297
  • For you use the string to Geometry that cant convert. – lindexi Jul 17 '17 at 10:40
  • I cant run your code but I can run my code. – lindexi Jul 17 '17 at 11:21
  • You are right, mine does not work. Not only it compiles, but it fails silently, without any message in the debug output. And it works in `Path` for example, but does not work in UserControl. It's unbelieveable to what strange, buggy and unusable state Microsoft managed to get XAML after all those years of "evolution" – Liero Jul 17 '17 at 11:39
  • I think you can use bind and it's a easy way. – lindexi Jul 17 '17 at 11:41

2 Answers2

2

What you are trying to do is perfectly working in WPF but unfortunately, it is not supported on UWP...

The only way I've found is to declare your path in the page/app resources and hence, by able to use the move and draw syntax

<Page.Resources>
    <Path x:Key="pp" Data="F1 M 24.0033,56.0078L 24.0033,38.0053L 22.0031,40.0056L 19.0027,35.0049L 38.0053,20.0028L 45.0063,25.5299L 45.0063,21.753L 49.0068,21.0029L 49.0068,28.6882L 57.008,35.0049L 54.0075,40.0056L 52.0073,38.0053L 52.0073,56.0078L 24.0033,56.0078 Z M 38.0053,26.9204L 27.0038,36.005L 27.0038,53.0074L 33.0046,53.0074L 33.0046,42.006L 43.006,42.006L 43.006,53.0074L 49.0068,53.0074L 49.0068,36.005L 38.0053,26.9204 Z" />
    <local:PathToFiguresConverter x:Key="converter" />
</Page.Resources>

And then use a converter to extract the created PathGeometry Data and provide them to the path object :

class PathToFiguresConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        var path = value as Path;
        var figures = (path.Data as PathGeometry).Figures;
        return figures;
    }

    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        throw new NotImplementedException();
    }
}

In the page/control:

<Path Fill="{ThemeResource SystemControlForegroundAccentBrush}">
    <Path.Data>
        <PathGeometry Figures="{Binding Source={StaticResource pp}, Converter={StaticResource converter} }" />
    </Path.Data>
</Path>

That also means that in your case, you will have to change your dependency property to :

public PathFigureCollection IconData
{
    get { return (PathFigureCollection )GetValue(IconDataProperty); }
    set { SetValue(IconDataProperty, value); }
}

public static readonly DependencyProperty IconDataProperty = 
    DependencyProperty.Register(nameof(IconData), typeof(PathFigureCollection ), typeof(Header), [...])
Vincent
  • 3,656
  • 1
  • 23
  • 32
  • Why don't you just bind to data? `` – Liero Jul 17 '17 at 11:27
  • @Liero For pp is Path but path.data is Geometry – lindexi Jul 17 '17 at 11:35
  • @lindexi: and? Path.Data is geometry and that is exactly what you need to get. Remove your PathGeometry element and bind directly Path.Data to pp.data. It should work – Liero Jul 17 '17 at 11:43
  • Binding a geometry to a path is not working (at least I've not been able to make it work). My guess is that the Geometry object is bound to its parent container. The PathFiguresCollection that we set in PathGeoamtry.Figures does not have this restriction and can be copied over several Path containers. – Vincent Jul 17 '17 at 13:11
  • Why dont you bind path figures then? `` I've tried it and it works in runtime, however the stupid designer complains **Value does not falls into expected range** – Liero Jul 18 '17 at 07:07
0

A easy way to fix it is use bind.

You can use bind and set the source and convert to convert the string to Geometry.

The code is below.

public class GeometryConvert : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        if (value is string str)
        {
            var geometry = (Geometry) XamlReader.Load(
                "<Geometry xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'>"
                + str + "</Geometry>");
            return geometry;
        }
        return null;
    }

    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        throw new NotImplementedException();
    }
}

And you should change your code to

<local:GeometryConvert x:Key="GeometryConvert"></local:GeometryConvert>

<local:Header x:Name="HeaderPanel" IconData="{Binding Source={StaticResource HomeIconGeometry},Converter={StaticResource GeometryConvert}}" />

As I can see , I run my code as the image.

enter image description here

But I dont find a good way to change string to Geometry.

See: https://stackoverflow.com/a/34900291/6116637

lindexi
  • 4,182
  • 3
  • 19
  • 65