0

The Setting: I have a RichTextBox containing a hyperink and a DropDownButton somewhere else in my UI. Now when I click the button's DropDown open and afterwards click somewhere else on my UI, the DropDown is implemented to close, and check if it still owns the keyboardfocus so it can set its ToggleButton to focused again after the DropDown collapsed as intended.

The Problem: When clicking inside my RichTextBox I will face an InvalidOperationException caused by my method to check focus ownership. The call to VisualTreeHelper.GetParent(potentialSubControl) works fine for all elements that are part of the VisualTree. Apparently the focused Hyperlink (returned by FocusManager.GetFocusedElement()) is not part of the VisualTree and therefore is invalid input to GetParent(). Well, how can I find the parent (either logical parent or visual parent) of a hyperlink within my RichTextBox?

My method for determining focus ownership:

// inside DropDownButton.cs
protected override void OnLostFocus( RoutedEventArgs e )
{
    base.OnLostFocus( e );
    if (CloseOnLostFocus && !DropDown.IsFocused()) CloseDropDown();
}

// inside static class ControlExtensions.cs
public static bool IsFocused( this UIElement control )
{
    DependencyObject parent;
    for (DependencyObject potentialSubControl =
        FocusManager.GetFocusedElement() as DependencyObject;
        potentialSubControl != null; potentialSubControl = parent)
    {
        if (object.ReferenceEquals( potentialSubControl, control )) return true;

        try { parent = VisualTreeHelper.GetParent(potentialSubControl); }
        catch (InvalidOperationException)
        {
            // can happen when potentialSubControl is technically
            // not part of the visualTree
            // for example when FocusManager.GetFocusedElement()
            // returned a focused hyperlink (System.Windows.Documents.Hyperlink)
            // from within a text area
            parent = null;
        }
        if (parent == null) {
            FrameworkElement element = potentialSubControl as FrameworkElement;
            if (element != null) parent = element.Parent;
        }
    }
    return false;
}

[Edit] One potential idea to solve the issue: since Hyperlink is a DependencyObject I could try to access its inheritance context and find other DependencyObjects higher up in the tree and test them for being FrameworkElements. But I struggle to find any information about inheritance context in Silverlight.

Martin
  • 5,714
  • 2
  • 21
  • 41
  • hey amigo saw your msg, I'm currently bouncing around countries while on vacation, I'll take a look as soon as I can get settled somewhere with more than just the phone but there may be a delay, sorry for the timing man. Hopefully someone comes along before I can who hasn't been drinking. ;) – Chris W. Aug 04 '15 at 18:57
  • @ChrisW.: Thanks, I will be patient. For now I can live with the try-catch block. It's just not the right solution. It feels like wrapping some duct tape around a severed leg so no one notices. – Martin Aug 05 '15 at 08:42
  • Hmmm, I'd be curious what the overall goal of the UX is because I could probably show you how to accomplish it with a bit less complexity and allow you to have more ownership of the control structure. I'm in Munich today and leave for another country tomorrow, do you still have my personal email from that time a while back? chris@professionals......net? We can take this offline but I'm not back home for some time so expect delayed response. Cheers! – Chris W. Aug 08 '15 at 07:15
  • @ChrisW.: Can't find the email in my _sent_ folder. Well, what I try to accomplish boils down to: at any arbitrarily chosen point in time (some FocusLost event or DropDownClosed event), and for any given element of my UI tree, I need to be able to check via an extension method if that very element is focused. My current implementation chokes on focused hyperlinks. – Martin Aug 14 '15 at 11:51
  • Are you only experiencing this while your focus(es) are inside a RichTextBox or elsewhere also? – Chris W. Dec 03 '15 at 19:16
  • The `System.Windows.Documents.Hyperlink` that can occur inside a `RichTextBox` is the only thingy I found so far that can have focus but: is not derived from `UIElement` and is not part of the visualTree. So yes, I'm only experiencing this with a focus somewhere inside a `RichTextBox`. – Martin Dec 04 '15 at 08:57
  • Ya you have to look at the Inline as parent and find it as child of it specifically. I've got a bunch of stuff going on today but I'll see if I can't eek out some time to share a concept. – Chris W. Dec 04 '15 at 14:06
  • I found no way to go from an `Inline` element to the owner that hosts it. – Martin Dec 07 '15 at 14:39
  • Keep having to bounce back to this, I'm going to have track down your email again in my outbox so we can do more offline. Anyway, you can't hit even with like `blah.parent as inline;` or `blah.parent as hyperlink`? – Chris W. Dec 10 '15 at 19:50
  • During runtime, when I retrieve the currently focused element, I get a `DependencyObject` instance that is a `System.Windows.Documents.Hyperlink` (and I can cast it to that type if I need to) but it does not have a property `Parent`. That's my problem. – Martin Dec 21 '15 at 09:48

0 Answers0