A cross-platform UI framework for .NET
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

56 lines
2.0 KiB

using System;
using System.Reactive.Disposables;
using Avalonia.Utilities;
namespace Avalonia.Controls
{
public class NameScopeLocator
{
/// <summary>
/// Tracks a named control relative to another control.
/// </summary>
/// <param name="scope">The scope relative from which the object should be resolved.</param>
/// <param name="name">The name of the object to find.</param>
public static IObservable<object> Track(INameScope scope, string name)
{
return new NeverEndingSynchronousCompletionAsyncResultObservable<object>(scope.FindAsync(name));
}
// This class is implemented in such weird way because for some reason
// our binding system doesn't expect OnCompleted to be ever called and
// seems to treat it as binding cancellation or something
private class NeverEndingSynchronousCompletionAsyncResultObservable<T> : IObservable<T>
{
private T _value;
private SynchronousCompletionAsyncResult<T>? _asyncResult;
public NeverEndingSynchronousCompletionAsyncResultObservable(SynchronousCompletionAsyncResult<T> task)
{
if (task.IsCompleted)
_value = task.GetResult();
else
_asyncResult = task;
}
public IDisposable Subscribe(IObserver<T> observer)
{
if (_asyncResult?.IsCompleted == true)
{
_value = _asyncResult.Value.GetResult();
_asyncResult = null;
}
if (_asyncResult != null)
_asyncResult.Value.OnCompleted(() =>
{
observer.OnNext(_asyncResult.Value.GetResult());
});
else
observer.OnNext(_value);
return Disposable.Empty;
}
}
}
}