Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use a path data from a resource dictionary in UWP

This is trivial thing but yet it does not work.

I have something like this (it is in its own folder)

<ResourceDictionary>
    <Path x:Key="Test"
          Stroke="Black"
          Fill="Gray" 
          Data="M 10,100 C 10,300 300,-200 300,100" />
</ResourceDictionary>

Now I want to use it

<Page>
    <Page.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergeDictionaries>
                <ResourceDictionary Source="MyFolder/MyResourceDictionary.xaml/>
            </ResourceDictionary.MergeDictionaries>
        </ResourceDictionary>
    </Page.Resources>
    <ContentPresenter Content="{StaticResource Test}"/>
<Page/>

This will throw an exception, but I don't understand why. Exactly the same scenario in wpf works fine.

like image 237
adminSoftDK Avatar asked Feb 12 '16 13:02

adminSoftDK


People also ask

How do you use resource dictionary?

You can reference a resource throughout an app or from any XAML page within it. You can define your resources using a ResourceDictionary element from the Windows Runtime XAML. Then, you can reference your resources by using a StaticResource markup extension or ThemeResource markup extension.

What is path data in WPF?

The Path object represents a path shape and draws a path. The Path object draws both closed and open paths. A closed path is a shape that has the same start and end points and an open path is a shape that has different start and end points. The Fill property fills the interior of an ellipse.

What is a resource dictionary?

A resource dictionary is a repository for XAML resources, such as styles, that your app uses. You define the resources in XAML and can then retrieve them in XAML using the {StaticResource} markup extension and {ThemeResource} markup extension s. You can also access resources with code, but that is less common.


4 Answers

What about this solution?

Declare your GeometryData

<x:String x:Key="TestPathGeomerty">M 10,100 C 10,300 300,-200 300,100</x:String>

And use Path, instead ContentPresenter

<Path Data="{StaticResource TestPathGeomerty}"
      Fill="Red"/>
like image 140
Andrii Krupka Avatar answered Oct 15 '22 08:10

Andrii Krupka


In WPF, you can share the same instance within multiple controls. Unfortunately this is not possible in UWP.

The only solution that is guaranteed to work in UWP, is to define a DataTemplate in your resource containing the icon.

It is also better to use PathIcon instead of Path. PathIcon makes use of the Foreground property that will be inherited from your parent controls.

Here's an example on how to share Data paths for icons that will automatically scale (by using a Viewbox).

<Page.Resources>
    <DataTemplate x:Key="MagnifyingGlassPathIconCT">
        <Viewbox Stretch="Uniform">
            <PathIcon Data="M44,12 C32,12 22,22 22,34 22,46 32,56 44,56 56,56 66,46 66,34 66,22 56,12 44,12z M44,0 C63,0 78,15 78,34 78,53 63,68 44,68 40,68 36.5,67.5 33,66 L32.5,66 14,90 0,79.5 18,55.5 17,55 C13,49 10,42 10,34 10,15 25,0 44,0z" />
        </Viewbox>
    </DataTemplate>
</Page.Resources>

<StackPanel Padding="40" HorizontalAlignment="Left">
    <!--  Plain icon  -->
    <ContentPresenter
        Width="40"
        Height="40"
        ContentTemplate="{StaticResource MagnifyingGlassPathIconCT}"
        Foreground="Purple" />
    <!--  Icon with a border  -->
    <Border
        Width="40" Padding="7"
        Height="40"
        BorderBrush="Black"
        BorderThickness="2">
        <ContentPresenter ContentTemplate="{StaticResource MagnifyingGlassPathIconCT}" Foreground="Red" />
    </Border>
    <!--  Icon in a normal Button  -->
    <Button
        Width="40"
        Height="40"
        ContentTemplate="{StaticResource MagnifyingGlassPathIconCT}"
        Foreground="RoyalBlue" />
    <!--  Icon in an AppBarButton  -->
    <AppBarButton
        Width="40"
        ContentTemplate="{StaticResource MagnifyingGlassPathIconCT}"
        Foreground="Black"
        Label="Search" />
</StackPanel>

This is the result

like image 33
Wim Bokkers Avatar answered Oct 15 '22 09:10

Wim Bokkers


For a solution that lets you define it in a Style, try writting an attached property like this:

    public static string GetPathData(DependencyObject obj)
    {
        return (string)obj.GetValue(PathDataProperty);
    }

    public static void SetPathData(DependencyObject obj, string value)
    {
        obj.SetValue(PathDataProperty, value);
    }

    public static readonly DependencyProperty PathDataProperty =
        DependencyProperty.RegisterAttached("PathData", typeof(string), typeof(ElementExtensions), new PropertyMetadata(null, (d, e) =>
        {
            if (d is Path path)
            {
                Binding b = new Binding { Source = e.NewValue };
                path.SetBinding(Path.DataProperty, b);
            }
        }));

And now you can define a style like so:

<Style x:Key="BasePathStyle" TargetType="Path">
    <Setter Property="e:ElementExtensions.PathData" Value="M 10,100 C 10,300 300,-200 300,100" />
</Style>

And then use it like so:

<Path Style="{StaticResource BasePathStyle}" />
like image 32
Johnny Westlake Avatar answered Oct 15 '22 08:10

Johnny Westlake


The Path.Data property is of type Geometry so define it as a Geometry instead of a string

<Geometry x:Key="TestPathGeomerty">M 10,100 C 10,300 300,-200 300,100</Geometry>

<Path Data="{StaticResource TestPathGeomerty}"
      Fill="Red"/>
like image 26
Fredrik Hedblad Avatar answered Oct 15 '22 08:10

Fredrik Hedblad