4 changed files with 328 additions and 1 deletions
@ -0,0 +1,41 @@ |
|||
// Copyright (c) The Avalonia Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
using System; |
|||
using Avalonia.Controls; |
|||
using Avalonia.Data; |
|||
using Portable.Xaml.Markup; |
|||
|
|||
namespace Avalonia.Markup.Xaml.MarkupExtensions |
|||
{ |
|||
public class DynamicResourceExtension : MarkupExtension, IBinding |
|||
{ |
|||
public DynamicResourceExtension() |
|||
{ |
|||
} |
|||
|
|||
public DynamicResourceExtension(string resourceKey) |
|||
{ |
|||
ResourceKey = resourceKey; |
|||
} |
|||
|
|||
public string ResourceKey { get; set; } |
|||
|
|||
public override object ProvideValue(IServiceProvider serviceProvider) => this; |
|||
|
|||
InstancedBinding IBinding.Initiate( |
|||
IAvaloniaObject target, |
|||
AvaloniaProperty targetProperty, |
|||
object anchor, |
|||
bool enableDataValidation) |
|||
{ |
|||
if (target is IControl control) |
|||
{ |
|||
var resource = control.FindResource(ResourceKey); |
|||
return new InstancedBinding(resource); |
|||
} |
|||
|
|||
return null; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,285 @@ |
|||
// Copyright (c) The Avalonia 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.Linq; |
|||
using Avalonia.Controls; |
|||
using Avalonia.Controls.Presenters; |
|||
using Avalonia.Controls.Templates; |
|||
using Avalonia.Markup.Xaml.Data; |
|||
using Avalonia.Media; |
|||
using Avalonia.Styling; |
|||
using Avalonia.UnitTests; |
|||
using Avalonia.VisualTree; |
|||
using Xunit; |
|||
|
|||
namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions |
|||
{ |
|||
public class DynamicResourceTests |
|||
{ |
|||
[Fact] |
|||
public void DynamicResource_Can_Be_Assigned_To_Property() |
|||
{ |
|||
var xaml = @"
|
|||
<UserControl xmlns='https://github.com/avaloniaui'
|
|||
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
|
|||
<UserControl.Resources> |
|||
<SolidColorBrush x:Key='brush'>#ff506070</SolidColorBrush> |
|||
</UserControl.Resources> |
|||
|
|||
<Border Name='border' Background='{DynamicResource brush}'/> |
|||
</UserControl>";
|
|||
|
|||
var loader = new AvaloniaXamlLoader(); |
|||
var userControl = (UserControl)loader.Load(xaml); |
|||
var border = userControl.FindControl<Border>("border"); |
|||
|
|||
DelayedBinding.ApplyBindings(border); |
|||
|
|||
var brush = (SolidColorBrush)border.Background; |
|||
Assert.Equal(0xff506070, brush.Color.ToUint32()); |
|||
} |
|||
|
|||
[Fact] |
|||
public void DynamicResource_From_Style_Can_Be_Assigned_To_Property() |
|||
{ |
|||
var xaml = @"
|
|||
<UserControl xmlns='https://github.com/avaloniaui'
|
|||
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
|
|||
<UserControl.Styles> |
|||
<Style> |
|||
<Style.Resources> |
|||
<SolidColorBrush x:Key='brush'>#ff506070</SolidColorBrush> |
|||
</Style.Resources> |
|||
</Style> |
|||
</UserControl.Styles> |
|||
|
|||
<Border Name='border' Background='{DynamicResource brush}'/> |
|||
</UserControl>";
|
|||
|
|||
var loader = new AvaloniaXamlLoader(); |
|||
var userControl = (UserControl)loader.Load(xaml); |
|||
var border = userControl.FindControl<Border>("border"); |
|||
|
|||
DelayedBinding.ApplyBindings(border); |
|||
|
|||
var brush = (SolidColorBrush)border.Background; |
|||
Assert.Equal(0xff506070, brush.Color.ToUint32()); |
|||
} |
|||
|
|||
[Fact] |
|||
public void DynamicResource_From_Application_Can_Be_Assigned_To_Property_In_Window() |
|||
{ |
|||
using (StyledWindow()) |
|||
{ |
|||
Application.Current.Resources.Add("brush", new SolidColorBrush(0xff506070)); |
|||
|
|||
var xaml = @"
|
|||
<Window xmlns='https://github.com/avaloniaui'
|
|||
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
|
|||
<Border Name='border' Background='{DynamicResource brush}'/> |
|||
</Window>";
|
|||
|
|||
var loader = new AvaloniaXamlLoader(); |
|||
var window = (Window)loader.Load(xaml); |
|||
var border = window.FindControl<Border>("border"); |
|||
|
|||
var brush = (SolidColorBrush)border.Background; |
|||
Assert.Equal(0xff506070, brush.Color.ToUint32()); |
|||
} |
|||
} |
|||
|
|||
[Fact] |
|||
public void DynamicResource_From_Application_Can_Be_Assigned_To_Property_In_UserControl() |
|||
{ |
|||
using (UnitTestApplication.Start(TestServices.StyledWindow)) |
|||
{ |
|||
Application.Current.Resources.Add("brush", new SolidColorBrush(0xff506070)); |
|||
|
|||
var xaml = @"
|
|||
<UserControl xmlns='https://github.com/avaloniaui'
|
|||
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
|
|||
<Border Name='border' Background='{DynamicResource brush}'/> |
|||
</UserControl>";
|
|||
|
|||
var loader = new AvaloniaXamlLoader(); |
|||
var userControl = (UserControl)loader.Load(xaml); |
|||
var border = userControl.FindControl<Border>("border"); |
|||
|
|||
// We don't actually know where the global styles are until we attach the control
|
|||
// to a window, as Window has StylingParent set to Application.
|
|||
var window = new Window { Content = userControl }; |
|||
window.Show(); |
|||
|
|||
var brush = (SolidColorBrush)border.Background; |
|||
Assert.Equal(0xff506070, brush.Color.ToUint32()); |
|||
} |
|||
} |
|||
|
|||
[Fact] |
|||
public void DynamicResource_Can_Be_Assigned_To_Setter() |
|||
{ |
|||
using (StyledWindow()) |
|||
{ |
|||
var xaml = @"
|
|||
<Window xmlns='https://github.com/avaloniaui'
|
|||
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
|
|||
<Window.Resources> |
|||
<SolidColorBrush x:Key='brush'>#ff506070</SolidColorBrush> |
|||
</Window.Resources> |
|||
<Window.Styles> |
|||
<Style Selector='Button'> |
|||
<Setter Property='Background' Value='{DynamicResource brush}'/> |
|||
</Style> |
|||
</Window.Styles> |
|||
<Button Name='button'/> |
|||
</Window>";
|
|||
|
|||
var loader = new AvaloniaXamlLoader(); |
|||
var window = (Window)loader.Load(xaml); |
|||
var button = window.FindControl<Button>("button"); |
|||
var brush = (SolidColorBrush)button.Background; |
|||
|
|||
Assert.Equal(0xff506070, brush.Color.ToUint32()); |
|||
} |
|||
} |
|||
|
|||
[Fact] |
|||
public void DynamicResource_From_Style_Can_Be_Assigned_To_Setter() |
|||
{ |
|||
using (StyledWindow()) |
|||
{ |
|||
var xaml = @"
|
|||
<Window xmlns='https://github.com/avaloniaui'
|
|||
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='{DynamicResource brush}'/> |
|||
</Style> |
|||
</Window.Styles> |
|||
<Button Name='button'/> |
|||
</Window>";
|
|||
|
|||
var loader = new AvaloniaXamlLoader(); |
|||
var window = (Window)loader.Load(xaml); |
|||
var button = window.FindControl<Button>("button"); |
|||
var brush = (SolidColorBrush)button.Background; |
|||
|
|||
Assert.Equal(0xff506070, brush.Color.ToUint32()); |
|||
} |
|||
} |
|||
|
|||
[Fact] |
|||
public void DynamicResource_Can_Be_Assigned_To_Setter_In_Styles_File() |
|||
{ |
|||
var styleXaml = @"
|
|||
<Styles xmlns='https://github.com/avaloniaui'
|
|||
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
|
|||
<Styles.Resources> |
|||
<SolidColorBrush x:Key='brush'>#ff506070</SolidColorBrush> |
|||
</Styles.Resources> |
|||
|
|||
<Style Selector='Border'> |
|||
<Setter Property='Background' Value='{DynamicResource brush}'/> |
|||
</Style> |
|||
</Styles>";
|
|||
|
|||
using (StyledWindow(assets: ("test:style.xaml", styleXaml))) |
|||
{ |
|||
var xaml = @"
|
|||
<Window xmlns='https://github.com/avaloniaui'
|
|||
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
|
|||
<Window.Styles> |
|||
<StyleInclude Source='test:style.xaml'/> |
|||
</Window.Styles> |
|||
<Border Name='border'/> |
|||
</Window>";
|
|||
|
|||
var loader = new AvaloniaXamlLoader(); |
|||
var window = (Window)loader.Load(xaml); |
|||
var border = window.FindControl<Border>("border"); |
|||
var brush = (SolidColorBrush)border.Background; |
|||
|
|||
Assert.Equal(0xff506070, brush.Color.ToUint32()); |
|||
} |
|||
} |
|||
|
|||
[Fact] |
|||
public void DynamicResource_Can_Be_Assigned_To_Property_In_ControlTemplate_In_Styles_File() |
|||
{ |
|||
var styleXaml = @"
|
|||
<Styles xmlns='https://github.com/avaloniaui'
|
|||
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
|
|||
<Styles.Resources> |
|||
<SolidColorBrush x:Key='brush'>#ff506070</SolidColorBrush> |
|||
</Styles.Resources> |
|||
|
|||
<Style Selector='Button'> |
|||
<Setter Property='Template'> |
|||
<ControlTemplate> |
|||
<Border Name='border' Background='{DynamicResource brush}'/> |
|||
</ControlTemplate> |
|||
</Setter> |
|||
</Style> |
|||
</Styles>";
|
|||
|
|||
using (StyledWindow(assets: ("test:style.xaml", styleXaml))) |
|||
{ |
|||
var xaml = @"
|
|||
<Window xmlns='https://github.com/avaloniaui'
|
|||
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
|
|||
<Window.Styles> |
|||
<StyleInclude Source='test:style.xaml'/> |
|||
</Window.Styles> |
|||
<Button Name='button'/> |
|||
</Window>";
|
|||
|
|||
var loader = new AvaloniaXamlLoader(); |
|||
var window = (Window)loader.Load(xaml); |
|||
var button = window.FindControl<Button>("button"); |
|||
|
|||
window.Show(); |
|||
|
|||
var border = (Border)button.GetVisualChildren().Single(); |
|||
var brush = (SolidColorBrush)border.Background; |
|||
|
|||
Assert.Equal(0xff506070, brush.Color.ToUint32()); |
|||
} |
|||
} |
|||
|
|||
private IDisposable StyledWindow(params (string, string)[] assets) |
|||
{ |
|||
var services = TestServices.StyledWindow.With( |
|||
assetLoader: new MockAssetLoader(assets), |
|||
theme: () => new Styles |
|||
{ |
|||
WindowStyle(), |
|||
}); |
|||
|
|||
return UnitTestApplication.Start(services); |
|||
} |
|||
|
|||
private Style WindowStyle() |
|||
{ |
|||
return new Style(x => x.OfType<Window>()) |
|||
{ |
|||
Setters = |
|||
{ |
|||
new Setter( |
|||
Window.TemplateProperty, |
|||
new FuncControlTemplate<Window>(x => |
|||
new ContentPresenter |
|||
{ |
|||
Name = "PART_ContentPresenter", |
|||
[!ContentPresenter.ContentProperty] = x[!Window.ContentProperty], |
|||
})) |
|||
} |
|||
}; |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue