Question

I have a nested TreeView where I bind the doubleclick event on each item so that the text of the node is changed to an editable textbox. I then use the lostFocus eventhandler to remove the textbox and restore the text.

  void treeViewItemWithMenu_MouseDoubleClick(object sender, MouseButtonEventArgs e)
    {
        if (selected == e.Source)
        {
            TextBox tb = new TextBox();
            tb.Text = this.Header.ToString();
            tb.Focus();
            tb.LostFocus += new RoutedEventHandler(tb_LostFocus);
            this.Header = tb;
            var a = e.OriginalSource;
            e.Handled = true;
        }
    }


    void tb_LostFocus(object sender, RoutedEventArgs e)
    {
        this.Header = ((TextBox)(this.Header)).Text;
    }

Unfortantly it does not seem like the lostFocus event is working correctly. When I click outside the textbox, it does not fire at all. I can even doubleclick on another node and it goes into edit mode (ie becomes a text box) while the first textbox seems to still have focus. Lost focus does not fire untill i start going back and forth between two text boxes.

I'm using vs2010 rc with project set to .net 3.5.

Was it helpful?

Solution

Oh my! Pardon my saying so, but every regular WPF user who has read your question has probably shaken their head in pity. We feel sad for you because you haven't yet learned the true "Zen of WPF", which is leveraging data binding, templates and triggers to make your UI dynamic rather than doing it the old-fashioned way. WPF is beautiful because of this ability. It also makes things "1000%" easier.

I recommend you change your UI to use a Trigger on your TreeViewItem to replace your HeaderTemplate based on a property you define in the TreeViewItem. Set this property true when the item is double-clicked. Set it false when IsKeyboardFocusWithin goes false (you can override metadata and add a PropertyChangedCallback for this).

As far as your LostFocus problem goes, I suspect your problem is that you have multiple focus scopes or it is a bug in the RC. Without seeing your XAML I can't say much more than that.

Additional details on doing this the "WPF way"

Here are some of the details on how to implement this using an attached property, triggers and templates.

Your templates can be as simple or as complex as you want. Here's simple:

<DataTemplate x:Key="NormalTemplate">
  <ContentPresenter />
</DataTemplate>

<DataTemplate x:Key="TextBoxTemplate">
  <TextBox Text="{Binding}" />
</DataTemplate>

Here is what your style would look like:

<Style TargetType="TreeViewItem">
  <Setter Property="HeaderTemplate" Value="{StaticResource NormalTemplate}" />
  <Trigger Property="local:MyWindowClass.ShowTextBox" Value="true">
    <Setter Property="HeaderTemplate" Value="{StaticResource TextBoxTemplate}" />
  </Trigger>
</Style>

The attached property "ShowTextBox" can be created in MyWindowClass using the "propa" snippet - just type "propa" and hit tab, then fill in the blanks.

To switch the item to show the textbox, just:

SetShowTextBox(item, true);

To switch it back:

SetShowTextBox(item, false);

I hope this helps.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top