Browse Source

Allow {StyleResource} in setter.

pull/464/head
Steven Kirk 10 years ago
parent
commit
f62f32c83c
  1. 87
      src/Markup/Perspex.Markup.Xaml/Data/StyleResourceBinding.cs
  2. 30
      src/Markup/Perspex.Markup.Xaml/MarkupExtensions/StyleResourceExtension.cs
  3. 2
      src/Markup/Perspex.Markup.Xaml/OmniXAML
  4. 1
      src/Markup/Perspex.Markup.Xaml/Perspex.Markup.Xaml.csproj
  5. 32
      tests/Perspex.Markup.Xaml.UnitTests/StyleTests.cs

87
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
{
/// <summary>
/// Initializes a new instance of the <see cref="StyleResourceBinding"/> class.
/// </summary>
/// <param name="name">The resource name.</param>
public StyleResourceBinding(string name)
{
Name = name;
}
/// <inheritdoc/>
public BindingMode Mode => BindingMode.OneTime;
/// <summary>
/// Gets the resource name.
/// </summary>
public string Name { get; }
/// <inheritdoc/>
public BindingPriority Priority => BindingPriority.LocalValue;
/// <inheritdoc/>
public ISubject<object> CreateSubject(IPerspexObject target, PerspexProperty targetProperty)
{
return new Subject(target, Name);
}
private class Subject : ISubject<object>
{
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<object> 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();
});
}
}
}
}

30
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; }

2
src/Markup/Perspex.Markup.Xaml/OmniXAML

@ -1 +1 @@
Subproject commit e1a5fb60b09862183ba5c48c36a52bea7a66bd42
Subproject commit 2b41f290bdf4dce07730a8f55622a637f966945b

1
src/Markup/Perspex.Markup.Xaml/Perspex.Markup.Xaml.csproj

@ -78,6 +78,7 @@
<Compile Include="Data\MultiBinding.cs" />
<Compile Include="Data\RelativeSource.cs" />
<Compile Include="Data\SourceBindingEndpoint.cs" />
<Compile Include="Data\StyleResourceBinding.cs" />
<Compile Include="Data\TargetBindingEndpoint.cs" />
<Compile Include="MarkupExtensions\StyleResourceExtension.cs" />
<Compile Include="MarkupExtensions\BindingExtension.cs" />

32
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 = @"
<UserControl xmlns='https://github.com/perspex'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
<UserControl.Styles>
// 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 = @"
<Window xmlns='https://github.com/perspex'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
<Window.Styles>
<Style>
<Style.Resources>
<SolidColorBrush x:Key='brush'>#ff506070</SolidColorBrush>
</Style.Resources>
</Style>
<Style Selector='Button'>
<Setter Property='Background' Value='#ff808080'/>
<Setter Property='Background' Value='{StyleResource brush}'/>
</Style>
</UserControl.Styles>
</UserControl>";
</Window.Styles>
<Button Name='button'/>
</Window>";
var loader = new PerspexXamlLoader();
var userControl = (UserControl)loader.Load(xaml);
var style = (Style)userControl.Styles[1];
var setter = (Setter)style.Setters.Single();
var loader = new PerspexXamlLoader();
var window = (Window)loader.Load(xaml);
var button = window.FindControl<Button>("button");
var brush = (SolidColorBrush)button.Background;
Assert.NotNull(setter.Value);
Assert.Equal(0xff506070, brush.Color.ToUint32());
}
}
[Fact]

Loading…
Cancel
Save