using System; using Avalonia.Reactive; namespace Avalonia.Controls { public static class ResourceNodeExtensions { /// /// Finds the specified resource by searching up the logical tree and then global styles. /// /// The control. /// The resource key. /// The resource, or if not found. public static object FindResource(this IResourceNode control, object key) { if (control.TryFindResource(key, out var value)) { return value; } return AvaloniaProperty.UnsetValue; } /// /// Tries to the specified resource by searching up the logical tree and then global styles. /// /// The control. /// The resource key. /// On return, contains the resource if found, otherwise null. /// True if the resource was found; otherwise false. public static bool TryFindResource(this IResourceNode control, object key, out object value) { Contract.Requires(control != null); Contract.Requires(key != null); var current = control; while (current != null) { if (current is IResourceNode host) { if (host.TryGetResource(key, out value)) { return true; } } current = current.ResourceParent; } value = null; return false; } public static IObservable GetResourceObservable(this IResourceNode target, object key) { return new ResourceObservable(target, key); } private class ResourceObservable : LightweightObservableBase { private readonly IResourceNode _target; private readonly object _key; public ResourceObservable(IResourceNode target, object key) { _target = target; _key = key; } protected override void Initialize() { _target.ResourcesChanged += ResourcesChanged; } protected override void Deinitialize() { _target.ResourcesChanged -= ResourcesChanged; } protected override void Subscribed(IObserver observer, bool first) { observer.OnNext(_target.FindResource(_key)); } private void ResourcesChanged(object sender, ResourcesChangedEventArgs e) { PublishNext(_target.FindResource(_key)); } } } }