From f69768af0fbc77eb7959acb742074a616a9e2d3c Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 10 Sep 2021 11:53:18 +0100 Subject: [PATCH] Merge pull request #6566 from AvaloniaUI/fixes/compiled-binding-support-IDataContextProvider CompiledBinding correctly locates IDataContextProvider as anchor. --- src/Markup/Avalonia.Markup.Xaml/Extensions.cs | 23 +++++++++++++++++++ .../CompiledBindingExtension.cs | 18 +-------------- .../ReflectionBindingExtension.cs | 23 +------------------ 3 files changed, 25 insertions(+), 39 deletions(-) diff --git a/src/Markup/Avalonia.Markup.Xaml/Extensions.cs b/src/Markup/Avalonia.Markup.Xaml/Extensions.cs index fe3fd44c1c..263750c316 100644 --- a/src/Markup/Avalonia.Markup.Xaml/Extensions.cs +++ b/src/Markup/Avalonia.Markup.Xaml/Extensions.cs @@ -2,7 +2,9 @@ using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; +using Avalonia.Controls; using Avalonia.Markup.Xaml.XamlIl.Runtime; +using Avalonia.Styling; namespace Avalonia.Markup.Xaml { @@ -32,5 +34,26 @@ namespace Avalonia.Markup.Xaml string name = string.IsNullOrEmpty(namespacePrefix) ? type : $"{namespacePrefix}:{type}"; return tr?.Resolve(name); } + + public static object GetDefaultAnchor(this IServiceProvider provider) + { + // If the target is not a control, so we need to find an anchor that will let us look + // up named controls and style resources. First look for the closest IControl in + // the context. + object anchor = provider.GetFirstParent(); + + if (anchor is null) + { + // Try to find IDataContextProvider, this was added to allow us to find + // a datacontext for Application class when using NativeMenuItems. + anchor = provider.GetFirstParent(); + } + + // If a control was not found, then try to find the highest-level style as the XAML + // file could be a XAML file containing only styles. + return anchor ?? + provider.GetService()?.RootObject as IStyle ?? + provider.GetLastParent(); + } } } diff --git a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindingExtension.cs b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindingExtension.cs index 17d2ea7ae9..41de2355aa 100644 --- a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindingExtension.cs +++ b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindingExtension.cs @@ -1,7 +1,5 @@ using System; using Avalonia.Data; -using Avalonia.Controls; -using Avalonia.Styling; using Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings; using Avalonia.Data.Core; using Avalonia.Markup.Parsers; @@ -33,24 +31,10 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions Priority = Priority, StringFormat = StringFormat, Source = Source, - DefaultAnchor = new WeakReference(GetDefaultAnchor(provider)) + DefaultAnchor = new WeakReference(provider.GetDefaultAnchor()) }; } - private static object GetDefaultAnchor(IServiceProvider provider) - { - // If the target is not a control, so we need to find an anchor that will let us look - // up named controls and style resources. First look for the closest IControl in - // the context. - object anchor = provider.GetFirstParent(); - - // If a control was not found, then try to find the highest-level style as the XAML - // file could be a XAML file containing only styles. - return anchor ?? - provider.GetService()?.RootObject as IStyle ?? - provider.GetLastParent(); - } - protected override ExpressionObserver CreateExpressionObserver(IAvaloniaObject target, AvaloniaProperty targetProperty, object anchor, bool enableDataValidation) { if (Source != null) diff --git a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/ReflectionBindingExtension.cs b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/ReflectionBindingExtension.cs index 10770365a3..d373ed852a 100644 --- a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/ReflectionBindingExtension.cs +++ b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/ReflectionBindingExtension.cs @@ -37,33 +37,12 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions Source = Source, StringFormat = StringFormat, RelativeSource = RelativeSource, - DefaultAnchor = new WeakReference(GetDefaultAnchor(descriptorContext)), + DefaultAnchor = new WeakReference(descriptorContext.GetDefaultAnchor()), TargetNullValue = TargetNullValue, NameScope = new WeakReference(serviceProvider.GetService()) }; } - private static object GetDefaultAnchor(IServiceProvider context) - { - // If the target is not a control, so we need to find an anchor that will let us look - // up named controls and style resources. First look for the closest IControl in - // the context. - object anchor = context.GetFirstParent(); - - if(anchor is null) - { - // Try to find IDataContextProvider, this was added to allow us to find - // a datacontext for Application class when using NativeMenuItems. - anchor = context.GetFirstParent(); - } - - // If a control was not found, then try to find the highest-level style as the XAML - // file could be a XAML file containing only styles. - return anchor ?? - context.GetService()?.RootObject as IStyle ?? - context.GetLastParent(); - } - public IValueConverter Converter { get; set; } public object ConverterParameter { get; set; }