R – Custom Shape in Silverlight (porting app from WPF)

shapesilverlightwpfxaml

I'm converting a WPF app to Silverlight.

The app includes a class which inherits from Shape. It overrides the DefiningGeometry property to return a Path object. However, the Silverlight Shape class doesn't have a DefiningGeometry property.

Reading on the internet I've found others with this same problem. The solution seems to involve inheriting from Control directly, and setting the Content property to the path. However, I also want to retain my event handlers (MouseEnter, MouseLeave, GotFocus, LostFocus) plus I would like it to keep it's position and resize proportionally to the rest of the application.

I'm mainly a back-end developer, so this isn't my forte – I'd appreciate it if anyone could give me an outline sample of how to achieve this.

Best Answer

You will not be able to produce a class that works in the same way because Silverlight does not support the creation of custom elements that derive from the Shape base class.

The reason it's impossible to create a custom shape in Silveright is that Silverlight does not share WPF's "visual layer". If you want to understand fully why what you're trying is impossible, you need to understand how Silverlight is very different from WPF here. (And if you don't care, skip the next 2 paragraphs.)

In WPF, you can work at two completely different levels: the visual layer, or the framework layer. The visual layer's services are provided by WindowsBase.dll and PresentationCore.dll. This provides basic rendering and input services. But if you want things like styling, data binding, layout, templating and so on, you need the framework services, and these are provided by PresentationFramework.dll. The shape types - Rectangle, Path, and so on - are all framework types - they derive from FrameworkElement and they support data binding, layout, animation and so on. But they are implemented on top of the visual layer - if you look at any of the Shape types in Reflector or ILDASM you'll see they all override the OnRender method, and that's where the code that defines the actual shape lives. (OnRender is a visual layer function.) And because the visual layer is a fully supported and documented API, you're free to write your own shapes in WPF - you can write exactly the same sort of code as you'll find in the built-in shape classes.

Silverlight doesn't make this visual/framework distinction - in Silverlight, WPF's visual layer has essentially collapsed into the framework layer. So if you look at the shape types in Reflector or ILDASM, you'll see that they contain no OnRender method, and they're almost empty. That's because in Silverlight, the shapes are all intrinsics - the plugin has built-in special handling for Ellipse, Path, and all the other shapes. So the set of shapes is not open to extension in Silverilght. There is no OnRender method to override in Silverlight. So you simply cannot write your own custom class that derives from Shape in Silverlight.

So, either a custom Control or a UserControl will be the way to go, I'm afraid. This shouldn't stop the MouseEnter and MouseLeave from working though. Have you actually found that those don't work? Or are you just assuming that they won't work?

Related Topic