Skip to content

Commit

Permalink
Merge pull request #6566 from AvaloniaUI/fixes/compiled-binding-suppo…
Browse files Browse the repository at this point in the history
…rt-IDataContextProvider

CompiledBinding correctly locates IDataContextProvider as anchor.
  • Loading branch information
danwalmsley committed Sep 13, 2021
1 parent 7eaf18c commit f69768a
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 39 deletions.
23 changes: 23 additions & 0 deletions src/Markup/Avalonia.Markup.Xaml/Extensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
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
{
Expand Down Expand Up @@ -32,5 +34,26 @@ public static Type ResolveType(this IServiceProvider ctx, string namespacePrefix
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<IControl>();

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<IDataContextProvider>();
}

// 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<IRootObjectProvider>()?.RootObject as IStyle ??
provider.GetLastParent<IStyle>();
}
}
}
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -33,24 +31,10 @@ public CompiledBindingExtension ProvideValue(IServiceProvider provider)
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<IControl>();

// 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<IRootObjectProvider>()?.RootObject as IStyle ??
provider.GetLastParent<IStyle>();
}

protected override ExpressionObserver CreateExpressionObserver(IAvaloniaObject target, AvaloniaProperty targetProperty, object anchor, bool enableDataValidation)
{
if (Source != null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,33 +37,12 @@ public Binding ProvideValue(IServiceProvider serviceProvider)
Source = Source,
StringFormat = StringFormat,
RelativeSource = RelativeSource,
DefaultAnchor = new WeakReference(GetDefaultAnchor(descriptorContext)),
DefaultAnchor = new WeakReference(descriptorContext.GetDefaultAnchor()),
TargetNullValue = TargetNullValue,
NameScope = new WeakReference<INameScope>(serviceProvider.GetService<INameScope>())
};
}

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<IControl>();

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<IDataContextProvider>();
}

// 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<IRootObjectProvider>()?.RootObject as IStyle ??
context.GetLastParent<IStyle>();
}

public IValueConverter Converter { get; set; }

public object ConverterParameter { get; set; }
Expand Down

0 comments on commit f69768a

Please sign in to comment.