Search code examples
c#wpftreeviewtreeviewitem

TreeView SelectedItem behavior with TextBox children


The SelectedItemChanged event and SelectedItem property of TreeView do not occur when the TreeViewItem is an input control like Textbox. The sample code below illustrates the problem by placing a breakpoint in TreeView SelectedItemChanged event. This breakpoint will fire when "String Header" is selected, but not "Textbox Header".

I assume that the Textbox or RichTextbox (My real application) is eating some vital bubbling event. How can I get the TreeView SelectedItem to behave for a TextBox as it would for control like Label?

Note: If I can solve this issue I will need to two-way bind to SelectedItem as I am using MVVM and MEF. SelectedItem is readonly which is problem, which I plan to solve with ( http://silverscratch.blogspot.com/2010/11/two-way-binding-on-treeviewselecteditem.html ). I thought this related link might help someone.

XAML:

<TreeView SelectedItemChanged="TreeView_SelectedItemChanged">
    <TreeViewItem>
        <TreeViewItem.Header>
            <TextBox>
                Textbox Header
            </TextBox>
        </TreeViewItem.Header>
    </TreeViewItem>
    <TreeViewItem>
        <TreeViewItem.Header>
            String Header
        </TreeViewItem.Header>
    </TreeViewItem>
</TreeView>

Code Behind:

    private void TreeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
    {
        // Breakpoint will fire when "String Header" Selected
        // !!! Breakpoint does not fire when Textbox Selected
        var newValue = e.NewValue;
        var oldValue = e.OldValue;
    }

Thanks,


Solution

  • You should catch GotFocus event on your TreeView :

    <TreeView SelectedItemChanged="TreeView_SelectedItemChanged"
              GotFocus="UIElement_OnGotFocus">
       <TreeViewItem>
          <TreeViewItem.Header>
              <TextBox>Textbox Header</TextBox>
           </TreeViewItem.Header>
       </TreeViewItem>
       <TreeViewItem>
            <TreeViewItem.Header>String Header</TreeViewItem.Header>
       </TreeViewItem>
     </TreeView>
    
    private void UIElement_OnGotFocus(object sender, RoutedEventArgs e)
    {
        TreeViewItem item = UIHelpers.TryFindParent<TreeViewItem>   
                               ((DependencyObject) e.OriginalSource);
        if (item != null)
              item.IsSelected = true;
    }
    

    The implementation of TryFindParent you may found here:
    https://stackoverflow.com/a/4838168/1088908