
A new sample program using VG.net vector graphics, called PanZoom, demonstrates how to use the new Zoom property in the Canvas class. The program uses this simple code to zoom in when the user clicks on a context menu:
canvas.Zoom *= 1.25;
And this code to zoom out:
canvas.Zoom /= 1.25;
Some other changes in this release:
- Serialization to .myxaml xml files (see previous blog entry)
- Centralization of Image storage in an ImageManager attached to each Picture. By using the ImageManager, we eliminated redundant storage of identical bitmaps within .resx files. ImageManager serves the same purpose as ImageList in windows forms, but is easier to use, since Images are referenced by name, not by index.
- Many classes and properties were renamed. The API is now stable and can be used in production applications.

The latest VG.net beta release includes a MyXaml serializer, allowing you to save VG.net Pictures as xml files. Marc Clifton has written an article on CodeProject describing how we created an analog clock using the VG.net designer and a few lines of code for animation.
Download the MyXaml clock sample.
We first created the clock was as a standard VG.net application. We set the new MyXamlExport property to true in the designer, causing the designer to save a copy of the Clock Picture as a .myxaml file every time you click “Save.” Then we copied the animation code to the .myxaml file, to make it self-contained. You can also put dynamically compiled animation code in a separate code-behind file.
Here is another Picture included in the MyXaml sample (not animated yet):

At some point, we will make an animated robot arm.
Here is a small "LED bar" created in the VG.net designer: 
Here is the MyXaml output for the image above. It is straightforward and easy to read. Each Ellipse has a separate Fill, so they can be independently animated:
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<!--Generated by the VG.net designer at 4/13/2004 5:54:50 PM-->
<MyXaml xmlns:def="Definition"
xmlns="Prodige.Drawing, Prodige.Drawing"
xmlns:pds="Prodige.Drawing.Styles, Prodige.Drawing">
<Picture Name="LedBar">
<Elements>
<Rectangle Name="bar" Location="0, 0" Size="120, 30" CornerRadius="20" StyleReference="Bar"
DrawAction="Fill" />
<Ellipse Name="led1" Location="12.63158, 6" Size="18.94737, 18" DrawAction="Fill">
<Fill>
<pds:SolidFill Color="50, 205, 50" />
</Fill>
</Ellipse>
<Ellipse Name="led2" Location="37.89474, 6" Size="18.94737, 18" DrawAction="Fill">
<Fill>
<pds:SolidFill Color="50, 205, 50" />
</Fill>
</Ellipse>
<Ellipse Name="led3" Location="63.1579, 6" Size="18.94737, 18" DrawAction="Fill">
<Fill>
<pds:SolidFill Color="50, 205, 50" />
</Fill>
</Ellipse>
<Ellipse Name="led4" Location="88.42103, 6" Size="18.94737, 18" DrawAction="Fill">
<Fill>
<pds:SolidFill Color="50, 205, 50" />
</Fill>
</Ellipse>
</Elements>
<Styles>
<pds:Style Name="Bar">
<pds:Fill>
<pds:LinearGradientFill Angle="90" StartColor="128, 128, 255" />
</pds:Fill>
</pds:Style>
</Styles>
</Picture>
</MyXaml>
Update: version 2.2 of VG.net includes a much more beautiful version of the analog vector graphics clock. See this blog entry for more information, or download and run the clock. A screenshot is below:

This post is in response to Marc Clifton's blog entry describing the new MyXaml parsing logic. I have been working with Marc on a MyXaml serializer/deserializer for VG.net vector graphics. I work on the serializer, and Marc, of course, works on a generic deserializer (markup->objects). During this process, we realized XAML is a poor general purpose serialization format; it is optimized only for Avalon. Read Marc's blog for all the details.
As a result, MyXaml is evolving into a format designed specifically to support the designer infrastructure already available in the .NET framework. This will make MyXaml extremely powerful! As far as I can tell, this infrastructure support was ignored during the design of XAML.
In just a few days, we were able to create a VG.net serializer (invoked from the designer) producing MyXaml files functionally equivalent to code produced by the CodeDom serializer. Such a task would have been difficult using the XAML format, and the resulting markup would be ugly. Our plan is to make MyXaml the main xml serialization format for VG.net.
One great thing about the VG.net serializer is the general nature of the code: it is not so much a VG.net serializer, as a generic serializer for any components built according to the .NET designer serialization guidelines. If your component supports Visual Studio .NET CodeDom serialization, it will support MyXaml serialization!
I will write some additional blog entries describing how to create a MyXaml serializer. First, I will explain the different types of properties a generic serialization engine must support, and some complications for the MyXaml format.
There are three types of serialized properties in .NET, corresponding to the three types of DesignerSerializationVisibilityAttribute values:
- Visible, the default value for writable public properties. These can be serialized in xml either as string values, in tag attributes, or by using the class-property-class syntax. Within the VG.net serializer, we serialize a property to an xml attribute if the property Type has a corresponding TypeConverter that can convert from a string: <Rectangle Name=“Rect1“>. Otherwise, we use the class-property-class syntax, with a separate tag for the property name and the property value.
- Hidden. These are never serialized.
- Content. Used for read-only properties that need sub-properties serialized. Typically used for collection properties, Content means the property is not deserialized by creating an object and assigning it to the property. The property is usually read only, making assignment impossible.
We can divide Content properties into two categories:
- Collections, which are deserialized via Add or AddRange calls.
- Read-only properties that are not collections. These rare properties are deserialized by assigning values to the object returned on a property get: rootObject.A.B = value. In that example, the property A is read-only, and cannot be assigned, but we still need to serialize and deserialize properties within A, namely B.
Now, you may be wondering about this class-property-class syntax. If you don't want to look back at Marc's blog, here is a summary. At the top level, a tag specifies a class. Each tag below that specifies a property name. Each tag within a property tag specifies a class, the value for that property:
<Rectangle>
<Fill>
<SolidFill Color=”Blue” />
</Fill>
</Rectangle>
What should the syntax be for Content properties? For collections, Marc decided to place the items in the collection underneath the property tag. Implicitly, these objects are added to the collection:
<Group>
<Elements>
<Rectangle Name="rectangle1" Location="480, 280" Size="100, 80" />
<Rectangle Name="rectangle2" Text="Hello!" Location="300, 300" Size="100, 80" />
</Elements>
</Group>
The only problem with this approach is setting other properties in a collection. A collection may have other properties that need to be serialized in addition to the items. And one of the property names could conflict with an item class name. I see two ways to resolve this: either use an additional tag level, called Items, for the items, or use the compound property syntax for collection properties.
How should Content properties that are not collections be serialized? I don't think there are any such properties in VG.net. But a generic way to serialize such properties might be be to use the same format as a collection: first the property tag, then the properties within the Content property. There is no need to output another tag level for an object to assign to the Content property, since it is read only. In this example, A is a Content property within RootClass, and B a property within that
<RootClass>
<A>
<B> ... values for B ...
</B>
</A>
</RootClass>
This is easy to serialize and deserialize, but may throw off readers of the markup, since Content properties have one less level of tags then other properties. For consistency, it might be better to have that extra level, even though no object can be created and assigned to the Content property (in this example, A is read-only):
<RootClass>
<A>
<AType>
<B> ... values for B ...
</B>
</AType>
</A>
</RootClass>