From 797cbb433ba59b87fba152679b8ee4b42660a191 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Fri, 28 Mar 2014 05:45:45 +0100 Subject: [PATCH] Added TemplateBinding syntactic sugar. --- .../Controls/ContentControlTests.cs | 5 +-- Perspex.UnitTests/Styling/TestControlBase.cs | 2 +- .../Styling/TestTemplatedControl.cs | 2 +- Perspex/BindingExtensions.cs | 39 +++++++++++++++++++ Perspex/Perspex.csproj | 1 + Perspex/PerspexObject.cs | 32 +++++++++++---- Perspex/Styling/IStyleable.cs | 5 ++- Perspex/Themes/Default/ButtonStyle.cs | 10 +---- 8 files changed, 73 insertions(+), 23 deletions(-) create mode 100644 Perspex/BindingExtensions.cs diff --git a/Perspex.UnitTests/Controls/ContentControlTests.cs b/Perspex.UnitTests/Controls/ContentControlTests.cs index 027139b0ae..f862edfa53 100644 --- a/Perspex.UnitTests/Controls/ContentControlTests.cs +++ b/Perspex.UnitTests/Controls/ContentControlTests.cs @@ -71,10 +71,7 @@ namespace Perspex.UnitTests.Controls Border border = new Border(); border.Background = new Perspex.Media.SolidColorBrush(0xffffffff); ContentPresenter contentPresenter = new ContentPresenter(); - contentPresenter.Bind( - ContentPresenter.ContentProperty, - parent.GetObservable(ContentControl.ContentProperty), - BindingPriority.TemplatedParent); + contentPresenter.TemplateBinding(parent, ContentPresenter.ContentProperty); border.Content = contentPresenter; return border; }); diff --git a/Perspex.UnitTests/Styling/TestControlBase.cs b/Perspex.UnitTests/Styling/TestControlBase.cs index 8e274ca1de..796e28b883 100644 --- a/Perspex.UnitTests/Styling/TestControlBase.cs +++ b/Perspex.UnitTests/Styling/TestControlBase.cs @@ -30,7 +30,7 @@ namespace Perspex.UnitTests.Styling set; } - public void Bind(PerspexProperty property, IObservable source, BindingPriority priority = BindingPriority.LocalValue) + public IDisposable Bind(PerspexProperty property, IObservable source, BindingPriority priority = BindingPriority.LocalValue) { throw new NotImplementedException(); } diff --git a/Perspex.UnitTests/Styling/TestTemplatedControl.cs b/Perspex.UnitTests/Styling/TestTemplatedControl.cs index fde5f3fa3f..9912bfe676 100644 --- a/Perspex.UnitTests/Styling/TestTemplatedControl.cs +++ b/Perspex.UnitTests/Styling/TestTemplatedControl.cs @@ -38,7 +38,7 @@ namespace Perspex.UnitTests.Styling throw new NotImplementedException(); } - public void Bind(PerspexProperty property, IObservable source, BindingPriority priority = BindingPriority.LocalValue) + public IDisposable Bind(PerspexProperty property, IObservable source, BindingPriority priority = BindingPriority.LocalValue) { throw new NotImplementedException(); } diff --git a/Perspex/BindingExtensions.cs b/Perspex/BindingExtensions.cs new file mode 100644 index 0000000000..8e54310da9 --- /dev/null +++ b/Perspex/BindingExtensions.cs @@ -0,0 +1,39 @@ +// ----------------------------------------------------------------------- +// +// Copyright 2014 MIT Licence. See licence.md for more information. +// +// ----------------------------------------------------------------------- + +namespace Perspex +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using System.Threading.Tasks; +using Perspex.Controls; + + /// + /// Provides binding utility extension methods. + /// + public static class BindingExtensions + { + /// + /// Binds a property in a template to the same property in the templated parent. + /// + /// The property type. + /// The control in the template. + /// The templated parent. + /// The property. + /// + /// A disposable which can be used to terminate the binding. + /// + public static IDisposable TemplateBinding( + this PerspexObject o, + ITemplatedControl templatedParent, + PerspexProperty property) + { + return o.Bind(property, templatedParent.GetObservable(property), BindingPriority.TemplatedParent); + } + } +} diff --git a/Perspex/Perspex.csproj b/Perspex/Perspex.csproj index 9d33cbd892..cdf03ea9f8 100644 --- a/Perspex/Perspex.csproj +++ b/Perspex/Perspex.csproj @@ -69,6 +69,7 @@ + diff --git a/Perspex/PerspexObject.cs b/Perspex/PerspexObject.cs index 6c25359e03..53ae51dc6f 100644 --- a/Perspex/PerspexObject.cs +++ b/Perspex/PerspexObject.cs @@ -417,6 +417,13 @@ namespace Perspex this.values.Add(property, v); } + this.Log().Debug(string.Format( + "Set local value of {0}.{1} (#{2:x8}) to {3}", + this.GetType().Name, + property.Name, + this.GetHashCode(), + value)); + v.Clear(priority); v.Add(Observable.Never().StartWith(value), priority); } @@ -441,7 +448,10 @@ namespace Perspex /// The property. /// The observable. /// The priority of the binding. - public void Bind( + /// + /// A disposable which can be used to terminate the binding. + /// + public IDisposable Bind( PerspexProperty property, IObservable source, BindingPriority priority = BindingPriority.LocalValue) @@ -449,6 +459,7 @@ namespace Perspex Contract.Requires(property != null); PriorityValue v; + IObservableDescription description = source as IObservableDescription; if (!this.values.TryGetValue(property, out v)) { @@ -461,13 +472,14 @@ namespace Perspex v.Clear((int)priority); } - v.Add(source, (int)priority); - this.Log().Debug(string.Format( - "Bound value of {0}.{1} (#{2:x8})", + "Bound value of {0}.{1} (#{2:x8}) to {3}", this.GetType().Name, property.Name, - this.GetHashCode())); + this.GetHashCode(), + description != null ? description.Description : "[Anonymous]")); + + return v.Add(source, (int)priority); } /// @@ -477,14 +489,17 @@ namespace Perspex /// The property. /// The observable. /// The priority of the binding. - public void Bind( + /// + /// A disposable which can be used to terminate the binding. + /// + public IDisposable Bind( PerspexProperty property, IObservable source, BindingPriority priority = BindingPriority.LocalValue) { Contract.Requires(property != null); - this.Bind((PerspexProperty)property, (IObservable)source, priority); + return this.Bind((PerspexProperty)property, (IObservable)source, priority); } private PriorityValue CreatePriorityValue(PerspexProperty property) @@ -505,10 +520,11 @@ namespace Perspex this.RaisePropertyChanged(property, oldValue, newValue); this.Log().Debug(string.Format( - "Set value of {0}.{1} (#{2:x8}) to {3}", + "Value of {0}.{1} (#{2:x8}) changed from {3} to {4}", this.GetType().Name, property.Name, this.GetHashCode(), + oldValue, newValue)); } }); diff --git a/Perspex/Styling/IStyleable.cs b/Perspex/Styling/IStyleable.cs index 79d7a65c58..11678c726b 100644 --- a/Perspex/Styling/IStyleable.cs +++ b/Perspex/Styling/IStyleable.cs @@ -36,7 +36,10 @@ namespace Perspex.Styling /// The property. /// The observable. /// The priority of the binding. - void Bind( + /// + /// A disposable which can be used to terminate the binding. + /// + IDisposable Bind( PerspexProperty property, IObservable source, BindingPriority priority = BindingPriority.LocalValue); diff --git a/Perspex/Themes/Default/ButtonStyle.cs b/Perspex/Themes/Default/ButtonStyle.cs index 65cbb74b68..1058b2129e 100644 --- a/Perspex/Themes/Default/ButtonStyle.cs +++ b/Perspex/Themes/Default/ButtonStyle.cs @@ -56,16 +56,10 @@ namespace Perspex.Themes.Default Border border = new Border(); border.Id = "border"; border.Padding = new Thickness(3); - border.Bind( - Border.BackgroundProperty, - control.GetObservable(Button.BackgroundProperty), - BindingPriority.TemplatedParent); + border.TemplateBinding(control, Border.BackgroundProperty); ContentPresenter contentPresenter = new ContentPresenter(); - contentPresenter.Bind( - ContentPresenter.ContentProperty, - control.GetObservable(Button.ContentProperty), - BindingPriority.TemplatedParent); + contentPresenter.TemplateBinding(control, ContentPresenter.ContentProperty); border.Content = contentPresenter; return border;