views:

56

answers:

1

I am looking for a way to create non-stroked regions for a StreamGeometry in xaml.

In other words, I want to know if it is possible to recreate the following code (taken from msdn) with the StreamGeometry Xaml markup syntax.

StreamGeometry geometry = new StreamGeometry();
geometry.FillRule = FillRule.EvenOdd;

using (StreamGeometryContext ctx = geometry.Open())
{

    ctx.BeginFigure(new Point(10, 100), true /* is filled */, true /* is closed */);

    ctx.LineTo(new Point(100, 100), false/* is not stroked */, false /* is smooth join */);

    ctx.LineTo(new Point(100, 50), true /* is stroked */, false /* is smooth join */);
}

I'm looking for a solution which works in WPF since Silverlight doesn't have a StreamGeometry.

A: 

Here is a direct translation using a PathGeometry:

<PathGeometry FillRule="EvenOdd">
  <PathFigure StartPoint="10,100" IsFilled="true" IsClosed="true">
    <LineSegment Point="100,100" IsStroked="false" IsSmoothJoin="false" />
    <LineSegment Point="100,50" IsStroked="true" IsSmoothJoin="false" />
  </PathFigure>
</PathGeometry>

This can be simplified by omitting the default values for FillRule, IsFilled, IsStroked and IsSmoothJoin, resulting in this:

<PathGeometry>
  <PathFigure StartPoint="10,100" IsClosed="true">
    <LineSegment Point="100,100" IsStroked="false" />
    <LineSegment Point="100,50" />
  </PathFigure>
</PathGeometry>

This must be done with a PathGeometry, not with the geometry mini-language (eg "M10,100 L100,100 100,50") because the mini-language provides no way to set IsStroked=false.

Since you need a StreamGeometry, I recommend you use GeometryExtensions.DrawGeometry method in this answer to convert the PathGeometry defined in XAML into a StreamGeometry.

I would be inclined to do this using a markup extension:

<local:ConvertToStreamGeometry>
  <PathGeometry>
    <PathFigure StartPoint="10,100" IsClosed="true">
      <LineSegment Point="100,100" IsStroked="false" />
      <LineSegment Point="100,50" />
    </PathFigure>
  </PathGeometry>
</local:ConvertToStreamGeometry>

The implementation of the markup extension is trivial:

[ContentProperty("Geometry")]
public class ConvertToStreamGeometry : MarkupExtension
{
  public Geometry Geometry { get; set; }
  public override object ProvideValue(IServiceProvider serviceProvider)
  {
    var result = new StreamGeometry();
    using(var ctx = result.Open())
      ctx.DrawGeometry(Geometry);
    return result;
  }
}

Note that this calls the GeometryExtensions.DrawGeometry extension method from the code in my earlier answer.

Ray Burns
Unfortunately, I need to use a StreamGeometry for efficiency reasons. I've done more research and it looks like it is indeed impossible to implement non-stroked segments within the geometry mini-language.
Aviv B.
Yes, I see the problem. I have extended my answer to explain how to construct the required StreamGeometry in XAML using a markup extension. Another alternative would be to implement your own geometry mini-language using a markup extension or an attached property.
Ray Burns