Skip to content

PathIconSource claims to support sharing but throws exception (AKA shared Geometry issue) #827

@verelpode

Description

@verelpode

A very common requirement is to use the same icon/symbol in multiple different buttons/places within an app. Nearly every non-trivial app needs this ability. The documentation for PathIconSource says this is supported:

PathIconSource is similar to PathIcon. However, because it is not a FrameworkElement, it can be shared.

It says it can be shared but if you try to share it, ArgumentException (HResult=0x80070057) is thrown. SymbolIconSource shares successfully but not PathIconSource.

Actually the underlying problem is that Geometry fails to share when you use the same Geometry instance with multiple instances of IconSourceElement or PathIcon or Shapes.Path.

In comparison, the older WPF-Desktop does support sharing of Geometry instances provided that you first invoke Geometry.Freeze (Freezable.Freeze). Unfortunately UWP does not support Freeze. (It supports Style.Seal but not Freeze.)

To work around this problem in UWP, we're forced to clone the Geometry instances whenever they're used in multiple places (very wasteful!), but how should that be done? UWP does not support the System.Windows.Media.Geometry.Clone method. For app authors to implement their own version of Clone is no small task because it requires manually copying all properties of all subclasses of Geometry, PathFigure, and all subclasses of PathSegment. Furthermore it's wasteful to have multiple clones of the same icons in RAM. It's also a substantial performance hit because whenever you create a new instance of a Page or UserControl, you must first clone all the icons/Geometry instances that the Page uses.

The problem of cloning Geometry is further worsened by the fact that UWP also lacks support for the "capacity" parameter in the constructor of PointCollection necessary for PolyBezierSegment.Points and other subclasses of PathSegment. The missing "capacity" parameter means that when you clone a PointCollection, the internal data is repeatedly reallocated/resized unnecessarily. This makes cloning even more expensive.

WPF-Desktop also has System.Windows.Media.StreamGeometry which is great for making efficient shared path-based icons, but again this feature is missing in UWP unfortunately.

Expected behavior

  • PathIconSource should do what the documentation says it does ("it can be shared"), meaning the ArgumentException should be eliminated.
  • It would be nice if Shapes.Path also supports shared Geometry but this is non-essential if at least PathIconSource supports sharing.
  • I like WPF's Geometry.Freeze (Freezable.Freeze) (and also UWP's Style.Seal) but I'd also be happy if the shared-icon solution is implemented in a different manner than Freeze or Seal.
  • In any event, please also support the "capacity" parameter. Even if the need for cloning is eliminated, the capacity parameter is still needed in other cases such as when deserializing a point list from a file, or when converting an SVG Path to a Xaml Geometry. Any case of building a PathGeometry can benefit from the capacity parameter.
  • Ideally UWP would also support an equivalent of System.Windows.Media.StreamGeometry, but the highest priority is to eliminate the ArgumentException when PathIconSource is shared.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions