From f62f32c83c8b620cb9940b2438352ca198faba2e Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Fri, 19 Feb 2016 17:53:05 +0100 Subject: [PATCH] Allow {StyleResource} in setter. --- .../Data/StyleResourceBinding.cs | 87 +++++++++++++++++++ .../StyleResourceExtension.cs | 30 +------ src/Markup/Perspex.Markup.Xaml/OmniXAML | 2 +- .../Perspex.Markup.Xaml.csproj | 1 + .../StyleTests.cs | 32 ++++--- 5 files changed, 111 insertions(+), 41 deletions(-) create mode 100644 src/Markup/Perspex.Markup.Xaml/Data/StyleResourceBinding.cs diff --git a/src/Markup/Perspex.Markup.Xaml/Data/StyleResourceBinding.cs b/src/Markup/Perspex.Markup.Xaml/Data/StyleResourceBinding.cs new file mode 100644 index 0000000000..f1c897dfd9 --- /dev/null +++ b/src/Markup/Perspex.Markup.Xaml/Data/StyleResourceBinding.cs @@ -0,0 +1,87 @@ +// Copyright (c) The Perspex Project. All rights reserved. +// Licensed under the MIT license. See licence.md file in the project root for full license information. + +using System; +using System.Reactive.Disposables; +using System.Reactive.Linq; +using System.Reactive.Subjects; +using Perspex.Data; +using Perspex.Styling; + +namespace Perspex.Markup.Xaml.Data +{ + public class StyleResourceBinding : IBinding + { + /// + /// Initializes a new instance of the class. + /// + /// The resource name. + public StyleResourceBinding(string name) + { + Name = name; + } + + /// + public BindingMode Mode => BindingMode.OneTime; + + /// + /// Gets the resource name. + /// + public string Name { get; } + + /// + public BindingPriority Priority => BindingPriority.LocalValue; + + /// + public ISubject CreateSubject(IPerspexObject target, PerspexProperty targetProperty) + { + return new Subject(target, Name); + } + + private class Subject : ISubject + { + private IPerspexObject _target; + private string _name; + + public Subject(IPerspexObject target, string name) + { + _target = target; + _name = name; + } + + public void OnCompleted() + { + } + + public void OnError(Exception error) + { + } + + public void OnNext(object value) + { + } + + public IDisposable Subscribe(IObserver observer) + { + // HACK around OmniXAML issue #84. + var po = (PerspexObject)_target; + var parent = PerspexPropertyRegistry.Instance.FindRegistered(po, "Parent"); + + return po.GetObservable(parent) + .Where(x => x != PerspexProperty.UnsetValue && x != null) + .Take(1) + .Subscribe(_ => + { + var resource = ((IStyleHost)_target).FindStyleResource(_name); + + if (resource != PerspexProperty.UnsetValue) + { + observer.OnNext(resource); + } + + observer.OnCompleted(); + }); + } + } + } +} diff --git a/src/Markup/Perspex.Markup.Xaml/MarkupExtensions/StyleResourceExtension.cs b/src/Markup/Perspex.Markup.Xaml/MarkupExtensions/StyleResourceExtension.cs index 1a1e5f12eb..48bec12be2 100644 --- a/src/Markup/Perspex.Markup.Xaml/MarkupExtensions/StyleResourceExtension.cs +++ b/src/Markup/Perspex.Markup.Xaml/MarkupExtensions/StyleResourceExtension.cs @@ -5,6 +5,7 @@ using System; using System.Reactive.Linq; using OmniXaml; using Perspex.LogicalTree; +using Perspex.Markup.Xaml.Data; using Perspex.Styling; namespace Perspex.Markup.Xaml.MarkupExtensions @@ -18,34 +19,7 @@ namespace Perspex.Markup.Xaml.MarkupExtensions public override object ProvideValue(MarkupExtensionContext extensionContext) { - var styleHost = extensionContext.TargetObject as IStyleHost; - - if (styleHost == null) - { - throw new ParseException( - $"StyleResource cannot be assigned to an object of type '{extensionContext.TargetObject.GetType()}'."); - } - - // HACK: This should be as simple as: - // return styleHost.FindStyleResource(Name); - // Waiting on OmniXAML issue #84 to be fixed before it can be that simple though. - var po = (PerspexObject)styleHost; - var parent = PerspexPropertyRegistry.Instance.FindRegistered(po, "Parent"); - - po.GetObservable(parent) - .Where(x => x != PerspexProperty.UnsetValue && x != null) - .Take(1) - .Subscribe(_ => - { - var resource = styleHost.FindStyleResource(Name); - - if (resource != PerspexProperty.UnsetValue) - { - extensionContext.TargetProperty.SetValue(extensionContext.TargetObject, resource); - } - }); - - return PerspexProperty.UnsetValue; + return new StyleResourceBinding(this.Name); } public string Name { get; set; } diff --git a/src/Markup/Perspex.Markup.Xaml/OmniXAML b/src/Markup/Perspex.Markup.Xaml/OmniXAML index e1a5fb60b0..2b41f290bd 160000 --- a/src/Markup/Perspex.Markup.Xaml/OmniXAML +++ b/src/Markup/Perspex.Markup.Xaml/OmniXAML @@ -1 +1 @@ -Subproject commit e1a5fb60b09862183ba5c48c36a52bea7a66bd42 +Subproject commit 2b41f290bdf4dce07730a8f55622a637f966945b diff --git a/src/Markup/Perspex.Markup.Xaml/Perspex.Markup.Xaml.csproj b/src/Markup/Perspex.Markup.Xaml/Perspex.Markup.Xaml.csproj index 35aff8a3a2..830eb87498 100644 --- a/src/Markup/Perspex.Markup.Xaml/Perspex.Markup.Xaml.csproj +++ b/src/Markup/Perspex.Markup.Xaml/Perspex.Markup.Xaml.csproj @@ -78,6 +78,7 @@ + diff --git a/tests/Perspex.Markup.Xaml.UnitTests/StyleTests.cs b/tests/Perspex.Markup.Xaml.UnitTests/StyleTests.cs index 321ac355fc..8fa212c17a 100644 --- a/tests/Perspex.Markup.Xaml.UnitTests/StyleTests.cs +++ b/tests/Perspex.Markup.Xaml.UnitTests/StyleTests.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Reactive.Linq; using Perspex.Controls; using Perspex.Data; +using Perspex.Input; using Perspex.Markup.Xaml.Data; using Perspex.Media; using Perspex.Styling; @@ -91,27 +92,34 @@ namespace Perspex.Markup.Xaml.UnitTests [Fact] public void StyleResource_Can_Be_Assigned_To_Setter() { - var xaml = @" - - + // For some reason this type can't always be found if we don't do this. + var hack = typeof(KeyboardNavigation); + + using (UnitTestApplication.Start(TestServices.StyledWindow)) + { + var xaml = @" + + - -"; + +