Browse Source

Static resource as binding converter

Enable using a `StaticResource` as a binding converter. Fixes #818.
pull/1136/head
Steven Kirk 9 years ago
parent
commit
2c1efe3773
  1. 7
      src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/DynamicResourceExtension.cs
  2. 27
      src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/StaticResourceExtension.cs
  3. 27
      tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/StaticResourceExtensionTests.cs
  4. 20
      tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/TestValueConverter.cs

7
src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/DynamicResourceExtension.cs

@ -3,7 +3,7 @@
using System; using System;
using System.ComponentModel; using System.ComponentModel;
using System.Reactive; using System.Linq;
using System.Reactive.Linq; using System.Reactive.Linq;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Data; using Avalonia.Data;
@ -62,7 +62,10 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions
var schemaContext = context.GetService<IXamlSchemaContextProvider>()?.SchemaContext; var schemaContext = context.GetService<IXamlSchemaContextProvider>()?.SchemaContext;
var ambientProvider = context.GetService<IAmbientProvider>(); var ambientProvider = context.GetService<IAmbientProvider>();
var xamlType = schemaContext.GetXamlType(typeof(T)); var xamlType = schemaContext.GetXamlType(typeof(T));
return ambientProvider.GetFirstAmbientValue(xamlType) as T;
// We override XamlType.CanAssignTo in BindingXamlType so the results we get back
// from GetAllAmbientValues aren't necessarily of the correct type.
return ambientProvider.GetAllAmbientValues(xamlType).OfType<T>().FirstOrDefault();
} }
} }
} }

27
src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/StaticResourceExtension.cs

@ -32,7 +32,7 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions
var schemaContext = context.GetService<IXamlSchemaContextProvider>()?.SchemaContext; var schemaContext = context.GetService<IXamlSchemaContextProvider>()?.SchemaContext;
var ambientProvider = context.GetService<IAmbientProvider>(); var ambientProvider = context.GetService<IAmbientProvider>();
var resourceProviderType = schemaContext.GetXamlType(typeof(IResourceProvider)); var resourceProviderType = schemaContext.GetXamlType(typeof(IResourceProvider));
var resourceProviders = ambientProvider.GetAllAmbientValues(resourceProviderType); var ambientValues = ambientProvider.GetAllAmbientValues(resourceProviderType);
// Look upwards though the ambient context for IResourceProviders which might be able // Look upwards though the ambient context for IResourceProviders which might be able
// to give us the resource. // to give us the resource.
@ -43,18 +43,23 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions
// //
// StaticResource_Can_Be_Assigned_To_Property_In_ControlTemplate_In_Styles_File // StaticResource_Can_Be_Assigned_To_Property_In_ControlTemplate_In_Styles_File
// //
foreach (IResourceProvider resourceProvider in resourceProviders) foreach (var ambientValue in ambientValues)
{ {
if (resourceProvider is IControl control && control.StylingParent != null) // We override XamlType.CanAssignTo in BindingXamlType so the results we get back
// from GetAllAmbientValues aren't necessarily of the correct type.
if (ambientValue is IResourceProvider resourceProvider)
{ {
// If we've got to a control that has a StylingParent then it's probably if (resourceProvider is IControl control && control.StylingParent != null)
// a top level control and its StylingParent is pointing to the global {
// styles. If this is case just do a FindResource on it. // If we've got to a control that has a StylingParent then it's probably
return control.FindResource(ResourceKey); // a top level control and its StylingParent is pointing to the global
} // styles. If this is case just do a FindResource on it.
else if (resourceProvider.TryGetResource(ResourceKey, out var value)) return control.FindResource(ResourceKey);
{ }
return value; else if (resourceProvider.TryGetResource(ResourceKey, out var value))
{
return value;
}
} }
} }

27
tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/StaticResourceExtensionTests.cs

@ -332,6 +332,33 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
Assert.NotNull(listBox.ItemTemplate); Assert.NotNull(listBox.ItemTemplate);
} }
[Fact]
public void StaticResource_Can_Be_Assigned_To_Converter()
{
using (StyledWindow())
{
var xaml = @"
<Window xmlns='https://github.com/avaloniaui'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'>
<Window.Resources>
<local:TestValueConverter x:Key='converter' Append='bar'/>
</Window.Resources>
<TextBlock Name='textBlock' Text='{Binding Converter={StaticResource converter}}'/>
</Window>";
var loader = new AvaloniaXamlLoader();
var window = (Window)loader.Load(xaml);
var textBlock = window.FindControl<TextBlock>("textBlock");
window.DataContext = "foo";
window.ApplyTemplate();
Assert.Equal("foobar", textBlock.Text);
}
}
[Fact] [Fact]
public void Control_Property_Is_Not_Updated_When_Parent_Is_Changed() public void Control_Property_Is_Not_Updated_When_Parent_Is_Changed()
{ {

20
tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/TestValueConverter.cs

@ -0,0 +1,20 @@
using System;
using System.Globalization;
namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
{
public class TestValueConverter : IValueConverter
{
public string Append { get; set; }
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return value.ToString() + Append;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
Loading…
Cancel
Save