/// <summary> /// Tracks a named control relative to another control. /// </summary> /// <param name="relativeTo"> /// The control relative from which the other control should be found. /// </param> /// <param name="name">The name of the control to find.</param> public static IObservable <ILogical> Track(ILogical relativeTo, string name) { var attached = Observable.FromEventPattern <LogicalTreeAttachmentEventArgs>( x => relativeTo.AttachedToLogicalTree += x, x => relativeTo.AttachedToLogicalTree -= x) .Select(x => ((ILogical)x.Sender).FindNameScope()) .StartWith(relativeTo.FindNameScope()); var detached = Observable.FromEventPattern <LogicalTreeAttachmentEventArgs>( x => relativeTo.DetachedFromLogicalTree += x, x => relativeTo.DetachedFromLogicalTree -= x) .Select(x => (INameScope)null); return(attached.Merge(detached).Select(nameScope => { if (nameScope != null) { var registered = Observable.FromEventPattern <NameScopeEventArgs>( x => nameScope.Registered += x, x => nameScope.Registered -= x) .Where(x => x.EventArgs.Name == name) .Select(x => x.EventArgs.Element) .OfType <ILogical>(); var unregistered = Observable.FromEventPattern <NameScopeEventArgs>( x => nameScope.Unregistered += x, x => nameScope.Unregistered -= x) .Where(x => x.EventArgs.Name == name) .Select(_ => (ILogical)null); return registered .StartWith(nameScope.Find <ILogical>(name)) .Merge(unregistered); } else { return Observable.Return <ILogical>(null); } }).Switch()); }