From c5d042c0948fdcdca214569feb5978b9f5973e36 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Tue, 15 Mar 2016 13:25:29 +0100 Subject: [PATCH] Started adding a guide for WPF devs. --- docs/tutorial/from-wpf.md | 142 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100644 docs/tutorial/from-wpf.md diff --git a/docs/tutorial/from-wpf.md b/docs/tutorial/from-wpf.md new file mode 100644 index 00000000000..11ab5262944 --- /dev/null +++ b/docs/tutorial/from-wpf.md @@ -0,0 +1,142 @@ +# Perspex for WPF Developers + +Perspex is in general very similar to WPF, but you will find differences. Here +are the most common: + +## Styling + +The most obvious difference from other XAML frameworks is that Perspex uses a +[CSS-like styling system](../spec/styles.md). Styles aren't stored in a +`Resources` collection as in WPF, they are stored in a separate `Styles` +collection: + + + + + + + Header + + +## DataTemplates + +As styles aren't stored in `Resources`, neither are `DataTemplates` ([in fact +there is no `Resources` collection](#Resources)). Instead, `DataTemplates` are +placed in a `DataTemplates` collection on each control (and on `Application`): + + + + + + + + + + + + + +## UIElement, FrameworkElement and Control + +WPF's `UIElement` and `FrameworkElement` are non-templated control base classes, +which roughly equate to the Perspex `Control` class. WPF's `Control` class on +the other hand is a templated control - Perspex's equivalent of this is +`TemplatedControl`. + +So to recap: + +- `UIElement`: `Control` +- `FrameworkElement`: `Control` +- `Control`: `TemplatedControl` + +## DependencyProperty + +The Perspex equivalent of `DependencyProperty` is `StyledProperty`, however +Perspex [has a richer property system than WPF](../spec/defining-properties.md), +and includes `DirectProperty` for turning standard CLR properties into Perspex +properties. The common base class of `StyledProperty` and `DirectProperty` +is `PerspexProperty`. + +# Resources + +There is no `Resources` collection on controls in Perspex, however `Style`s +do have a `Resources` collection for style-related resources. These can be +referred to using the `{StyleResource}` markup extension both inside and outside +styles. + +For non-style-related resources, we suggest defining them in code and referring +to them in markup using the `{Static}` markup extension. There are [various +reasons](http://www.codemag.com/article/1501091) for this, but briefly: + +- Resources have to be parsed +- The tree has to be traversed to find them +- XAML doesn't handle immutable objects +- XAML syntax can be long-winded compared to C# + +## Grid + +Perspex has a `Grid` panel just like WPF, however a common use of `Grid` in WPF +is to stack two controls on top of each other. For this purpose in Perspex you +can just use a `Panel` which is more lightweight than `Grid`. + +We don't yet support `SharedSizeScope` in `Grid`. + +## Tunnelling Events + +Perspex has tunnelling events (unlike UWP!) but they're not exposed via +separate `Preview` CLR event handlers. To subscribe to a tunnelling event you +must call `AddHandler` with `RoutingStrategies.Tunnel`: + +``` +target.AddHandler(InputElement.KeyDownEvent, OnPreviewKeyDown, RoutingStrategies.Tunnel); + +void OnPreviewKeyDown(object sender, KeyEventArgs e) +{ + // Handler code +} +``` + +## Class Handlers + +In WPF, class handlers for events can be added by calling +[EventManager.RegisterClassHandler](https://msdn.microsoft.com/en-us/library/ms597875.aspx). +An example of registering a class handler in WPF might be: + + static MyControl() + { + EventManager.RegisterClassHandler(typeof(MyControl), MyEvent, HandleMyEvent)); + } + + private static void HandleMyEvent(object sender, RoutedEventArgs e) + { + } + +The equivalent of this in Perspex would be: + + static MyControl() + { + MyEvent.AddClassHandler(x => x.HandleMyEvent); + } + + private void HandleMyEvent(object sender, RoutedEventArgs e) + { + } + +Notice that in WPF you have to add the class handler as a static method, whereas +in Perspex the class handler is not static: the notification is automatically +directed to the correct instance. + +## PropertyChangedCallback + +Listening to changes on DependencyProperties in WPF can be complex. When you +register a `DependencyProperty` you can supply a static `PropertyChangedCallback` +but if you want to listen to changes from elsewhere [things can get complicated +and error-prone](http://stackoverflow.com/questions/23682232). + +In Perspex, there is no `PropertyChangedCallback` at the time of registration, +instead a class listener is [added to the control's static constructor in much +the same way that event class listeners are added](../spec/working-with-properties.md#Subscribing%20%to%20%a%20%Property%20%on%20%Any%20%Object).