diff --git a/Docs/intro.md b/Docs/intro.md index aba5ea1489..08d8da812a 100644 --- a/Docs/intro.md +++ b/Docs/intro.md @@ -36,32 +36,36 @@ Attached Properties. So the challenge became to improve it. Delaring a DP in WPF looks something like this: - public static readonly DependencyProperty PropertyDeclaration = - DependencyProperty.Register( - "PropertyName", - typeof(PropertyType), - typeof(OwnerClass), - new FrameworkPropertyMetadata( - default(PropertyType), - FrameworkPropertyMetadataOptions.Inherits)); - - public PropertyType PropertyName - { - get { return (PropertyType)this.GetValue(PropertyDeclaration); } - set { this.SetValue(PropertyDeclaration, value); } - } +```csharp +public static readonly DependencyProperty PropertyDeclaration = +DependencyProperty.Register( + "PropertyName", + typeof(PropertyType), + typeof(OwnerClass), + new FrameworkPropertyMetadata( + default(PropertyType), + FrameworkPropertyMetadataOptions.Inherits)); + +public PropertyType PropertyName +{ + get { return (PropertyType)this.GetValue(PropertyDeclaration); } + set { this.SetValue(PropertyDeclaration, value); } +} +``` Eww! All that just to declare a single property. There's **A LOT** of boilerplate there. With generics and default parameters we can at least make it look a bit nicer: - public static readonly PerspexProperty PropertyDeclaration = - PerspexProperty.Register("PropertyName", inherits: true); +```csharp +public static readonly PerspexProperty PropertyDeclaration = +PerspexProperty.Register("PropertyName", inherits: true); - public PropertyType PropertyName - { - get { return this.GetValue(PropertyDeclaration); } - set { this.SetValue(PropertyDeclaration, value); } - } +public PropertyType PropertyName +{ + get { return this.GetValue(PropertyDeclaration); } + set { this.SetValue(PropertyDeclaration, value); } +} +``` What can we see here? @@ -77,34 +81,42 @@ write typeof() twice. Binding in Perspex uses Reactive Extensions' IObservable. To bind an IObservable to a property, use the Bind method: - control.Bind(BorderProperty, someObject.SomeObservable()); +```csharp +control.Bind(BorderProperty, someObject.SomeObservable()); +``` Note that because PerspexProperty is typed, we can check that the observable is of the correct type. To get the value of a property as an observable, call GetObservable(): - var observable = control.GetObservable(Control.FooProperty); +```csharp +var observable = control.GetObservable(Control.FooProperty); +``` ## Attached Properties and Binding Pt 2 Attached properties are set just like in WPF, using SetValue. But what about the [] operator? C# 6 will allow us to use [] array subscripts in object initializers. So how does this look? - var control = new Control - { - Property1 = "Foo", - [Attached.Property] = "Bar", - } +```csharp +var control = new Control +{ + Property1 = "Foo", +[Attached.Property] = "Bar", +} +``` Nice... Lets take this further: - var control = new Control - { - Property1 = "Foo", - [Attached.Property] = "Bar", - [!Property2] = something.SomeObservable, - } +```csharp +var control = new Control +{ + Property1 = "Foo", +[Attached.Property] = "Bar", + [!Property2] = something.SomeObservable, +} +``` Yep, by putting a bang in front of the property name you can **bind** to a property (attached or otherwise) from the object initializer. @@ -120,12 +132,14 @@ Binding to a property on another control? Easy: Two way binding? Just add two bangs: - var control = new Control - { - Property1 = "Foo", - [Attached.Property] = "Bar", - [!!Property2] = anotherControl[!!Property1], - } +```csharp +var control = new Control +{ + Property1 = "Foo", +[Attached.Property] = "Bar", + [!!Property2] = anotherControl[!!Property1], +} +``` ## Visual and Logical trees @@ -144,36 +158,42 @@ property, which is determined by... Styles in Perspex diverge from styles in WPF quite a lot, and move towards a more CSS-like system. It's probably easiest to show in an example. Here is the default style for the CheckBox control: - new Style(x => x.OfType()) - { - Setters = new[] - { - new Setter(Button.TemplateProperty, ControlTemplate.Create(this.Template)), - }, - }, - new Style(x => x.OfType().Template().Id("checkMark")) - { - Setters = new[] - { - new Setter(Shape.IsVisibleProperty, false), - }, - }, - new Style(x => x.OfType().Class(":checked").Template().Id("checkMark")) - { - Setters = new[] - { - new Setter(Shape.IsVisibleProperty, true), - }, - }, +```csharp +new Style(x => x.OfType()) +{ +Setters = new[] +{ + new Setter(Button.TemplateProperty, ControlTemplate.Create(this.Template)), +}, +}, +new Style(x => x.OfType().Template().Id("checkMark")) +{ +Setters = new[] +{ + new Setter(Shape.IsVisibleProperty, false), +}, +}, +new Style(x => x.OfType().Class(":checked").Template().Id("checkMark")) +{ +Setters = new[] +{ + new Setter(Shape.IsVisibleProperty, true), +}, +}, +``` Let's see what's happening here: - new Style(x => x.OfType()) +```csharp +new Style(x => x.OfType()) +``` The constructor for the Style class defines the selector. Here we're saying "*this style applies to all controls in the the visual tree of type CheckBox*". A more complex selector: - new Style(x => x.OfType().Class(":checked").Template().Id("checkMark")) +```csharp +new Style(x => x.OfType().Class(":checked").Template().Id("checkMark")) +``` This selector matches "*all controls with Id == "checkMark" in the template of a CheckBox with the class ':checked'"*. Each control has an Id property, and Ids in templates are considered to be in a