From e402eb8cdd3f7748e52005f395f0ecb8a3c73bdc Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Thu, 3 Dec 2015 22:36:27 +0100 Subject: [PATCH] Make template bindings complete on Template change. This fixes a leak - needs to be done in XAML as well though. --- src/Perspex.Base/BindingDescriptor.cs | 14 +++++++++++++- src/Perspex.Base/PerspexObject.cs | 19 ++++++++++++------- .../Primitives/TemplatedControl.cs | 17 +++++++++++++++++ 3 files changed, 42 insertions(+), 8 deletions(-) diff --git a/src/Perspex.Base/BindingDescriptor.cs b/src/Perspex.Base/BindingDescriptor.cs index 4ee4966a98..c0c8f3406f 100644 --- a/src/Perspex.Base/BindingDescriptor.cs +++ b/src/Perspex.Base/BindingDescriptor.cs @@ -78,6 +78,18 @@ namespace Perspex set; } + /// + /// Gets or sets the source observable. + /// + /// + /// If null, then . will be used. + /// + public IObservable SourceObservable + { + get; + set; + } + /// /// Gets a description of the binding. /// @@ -128,7 +140,7 @@ namespace Perspex /// protected override IDisposable SubscribeCore(IObserver observer) { - return Source.GetObservable(Property).Subscribe(observer); + return (SourceObservable ?? Source.GetObservable(Property)).Subscribe(observer); } } } diff --git a/src/Perspex.Base/PerspexObject.cs b/src/Perspex.Base/PerspexObject.cs index 70dff41dda..25e0ff48be 100644 --- a/src/Perspex.Base/PerspexObject.cs +++ b/src/Perspex.Base/PerspexObject.cs @@ -163,13 +163,7 @@ namespace Perspex { get { - return new BindingDescriptor - { - Mode = binding.Mode, - Priority = binding.Priority, - Property = binding.Property, - Source = this, - }; + return CreateBindingDescriptor(binding); } set @@ -203,6 +197,17 @@ namespace Perspex } } + protected virtual BindingDescriptor CreateBindingDescriptor(BindingDescriptor source) + { + return new BindingDescriptor + { + Mode = source.Mode, + Priority = source.Priority, + Property = source.Property, + Source = this, + }; + } + public bool CheckAccess() => Dispatcher.UIThread.CheckAccess(); public void VerifyAccess() => Dispatcher.UIThread.VerifyAccess(); diff --git a/src/Perspex.Controls/Primitives/TemplatedControl.cs b/src/Perspex.Controls/Primitives/TemplatedControl.cs index 92e1c4af88..2955c733b8 100644 --- a/src/Perspex.Controls/Primitives/TemplatedControl.cs +++ b/src/Perspex.Controls/Primitives/TemplatedControl.cs @@ -3,6 +3,7 @@ using System; using System.Linq; +using System.Reactive.Linq; using Perspex.Controls.Presenters; using Perspex.Controls.Templates; using Perspex.Media; @@ -211,6 +212,22 @@ namespace Perspex.Controls.Primitives } } + protected sealed override BindingDescriptor CreateBindingDescriptor(BindingDescriptor source) + { + var result = base.CreateBindingDescriptor(source); + + // If the binding is a template binding, then complete when the Template changes. + if (source.Priority == BindingPriority.TemplatedParent) + { + var templateChanged = GetObservable(TemplateProperty).Skip(1); + + result.SourceObservable = result.Source.GetObservable(result.Property) + .TakeUntil(templateChanged); + } + + return result; + } + /// /// Called when the control's template is applied. ///