3

I wish to bind a collection of viewmodels with X,Y,Radius properties to a CombinedGeometry of circles using Union. However it seems that CombinedGeometry only supports 2 Geometries.

Is there anyway around this limitation?

Example of what I'm aiming for

<Path Stroke="Black" StrokeThickness="1" Fill="#CCCCFF">
  <Path.Data>
    <CombinedGeometry GeometryCombineMode="Union" ItemsSource="{Binding Circles}">
      <CombinedGeometry.Template>
        <EllipseGeometry RadiusX="{Binding Radius}" RadiusY="{Binding Radius}" CenterX="{Binding X}" CenterY="{Binding Y}"/>
      </CombinedGeometry.Template>
    </CombinedGeometry>
  </Path.Data>
</Path>

It is indeed possible to have CombinedGeometries within CombinedGeometry as seen below. However, I don't know how to set it up so that it is easily bindable.

   <Path Stroke="Black" StrokeThickness="1" Fill="#CCCCFF">
        <Path.Data>

        <!-- Combines two geometries using the union combine mode. -->
        <CombinedGeometry GeometryCombineMode="Union">
            <CombinedGeometry.Geometry1>
                <CombinedGeometry GeometryCombineMode="Union">
                    <CombinedGeometry.Geometry1>
                        <EllipseGeometry RadiusX="50" RadiusY="50" Center="200,200" />
                    </CombinedGeometry.Geometry1>
                    <CombinedGeometry.Geometry2>
                        <EllipseGeometry RadiusX="50" RadiusY="50" Center="125,200" />
                    </CombinedGeometry.Geometry2>
                </CombinedGeometry>
            </CombinedGeometry.Geometry1>
            <CombinedGeometry.Geometry2>
                <CombinedGeometry GeometryCombineMode="Union">
                    <CombinedGeometry.Geometry1>
                        <EllipseGeometry RadiusX="50" RadiusY="50" Center="100,100" />
                    </CombinedGeometry.Geometry1>
                    <CombinedGeometry.Geometry2>
                        <EllipseGeometry RadiusX="50" RadiusY="50" Center="150,120" />
                    </CombinedGeometry.Geometry2>
                </CombinedGeometry>
            </CombinedGeometry.Geometry2>
        </CombinedGeometry>
    </Path.Data>
</Path>
Ying Chan
  • 53
  • 1
  • 5

3 Answers3

2

Are you looking for GeometryGroup ?

MSDN Code Sample :

<Path Stroke="Black" StrokeThickness="1" Fill="#CCCCFF">     
  <Path.Data>
    <!-- Creates a composite shape from three geometries. -->
    <GeometryGroup FillRule="EvenOdd">
      <LineGeometry StartPoint="10,10" EndPoint="50,30" />
      <EllipseGeometry Center="40,70" RadiusX="30" RadiusY="30" />          
      <RectangleGeometry Rect="30,55 100 30" />
    </GeometryGroup>      
  </Path.Data>  
</Path>
Gishu
  • 134,492
  • 47
  • 225
  • 308
  • 2
    It is close to what I want, but lacks the union feature. I need to merge overlapping shapes so that only 1 outline exists. I have attempted using 2 sets of Geometry groups, 1 for the fill and 1 for the outline, however in some cases I need the fill to be transparent which makes this method invalid. – Ying Chan May 03 '11 at 04:43
  • @Ying - Did you try the different options for the FillRule property ? Also if that fails to work - check if a CombinedGeometry can be composed of other CombinedGeometry objects. – Gishu May 03 '11 at 04:46
  • Yes, CombinedGeometry can be composed of other CombinedGeometry objects, but I got no idea how to set it up so that I can simply bind a collection to it. See my edited question – Ying Chan May 03 '11 at 04:49
  • @Ying - ` – Gishu May 03 '11 at 05:01
  • I want to be able to dynamically add and remove circles that will be unioned. Can you give me an example of how to do it with your idea? – Ying Chan May 03 '11 at 05:06
  • I'm not sure if Binding will help you here.. The obvious way to do this would be to use to use DataTemplates that will render a ViewModel object as a EllipseGeometry. However this whole business of composing CombinedGeometry objects looks like will have to be done via custom code... See also http://stackoverflow.com/questions/1593860 – Gishu May 03 '11 at 05:22
1

This code produces the same result as the second code by the OP:

<Path Stroke="Black" StrokeThickness="1" Fill="#CCCCFF">
    <Path.Data>
        <CombinedGeometry GeometryCombineMode="Union">
            <CombinedGeometry.Geometry1>
                <!-- any geometry here -->
                <GeometryGroup/>
            </CombinedGeometry.Geometry1>
            <CombinedGeometry.Geometry2>
                <GeometryGroup FillRule="Nonzero">
                    <EllipseGeometry RadiusX="50" RadiusY="50" Center="200,200" />
                    <EllipseGeometry RadiusX="50" RadiusY="50" Center="125,200" />
                    <EllipseGeometry RadiusX="50" RadiusY="50" Center="100,100" />
                    <EllipseGeometry RadiusX="50" RadiusY="50" Center="150,120" />
                </GeometryGroup>
            </CombinedGeometry.Geometry2>
        </CombinedGeometry>
    </Path.Data>
</Path>

And instead of all the <EllipseGeometry>, you can bind to a collection via Children="{Binding Circles}" in <GeometryGroup>.

Martin Schneider
  • 14,263
  • 7
  • 55
  • 58
0

I have kind of a similar problem and found a hepfull post here: How to make the border trim the child elements?

You could also try to create a converter that receives the collection in that binding and builds up the combined geometries as desired. I'll do exactly that now :)

Community
  • 1
  • 1
Chris
  • 527
  • 3
  • 15