tags:

views:

259

answers:

1

I have a nested treeview where I bind the doubleclik 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.

+2  A: 

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.

Ray Burns
I belive IsKeyboardFocusWithin is not good enough. When I click outside I do not think I change the keyboard focus. I think perhaps I need to trape the mouseDown event in the main window, then if the target is not my textbox, loose focus. This does not handle keyboard events like "tab" though, so I was hoping for some "lostFocus" event that did. btw: databinding when using a table with an internal parent child relation seemd more complicated, but I'd love a pointer to a howto/tutorial.
devzero
I'm not familiar with what is out there tutorial-wise, but in this case you have to do almost exactly what I said and no more: It is very simple. I'll add some more to the answer to make the details clearer. DataBinding to a table with an internal parent-child relation is not difficult either: Just add a property to your data model (or view model) that finds and returns the list of child objects and bind to it in your `HierarchicalDataTemplate`'s `ItemsSource` property.
Ray Burns