0
votes

In my WPF C# project, I've created a TreeView. Each TreeViewItem has a LostFocus event that must be raised when item lost its focus. I've also create a button that is needed to be clicked when user wants to change header of a certain TreeViewItem. User, after the selection in TreeView, can click on button and a TextBox appear replacing the TreeViewItem header. If user does not click on TextBox but click on another TreeViewItem, the LostFocus event is never raised. Otherwise, if user click on TextBox and then change focus, it is raised. I've also used textBox.Focus() and Keyboard.Focus(textBox) but the do not work. How can I fix this?

Just to be clear, before creating a post I've read another SO answer here

Here is the snippet code

 private void RenameButton_Click(object sender, RoutedEventArgs e)
     {

         TreeViewItem twItemSelected = (TreeViewItem)this.Treeview_PropertyDefinition.SelectedItem;                                                            
         var textBox = new TextBox()
         {
             Text = (String)twItemSelected.Header,
         };
         textBox.Focus();
         Keyboard.Focus(textBox);
         if (textBox.IsFocused)
             MessageBox.Show("focused");


         twItemSelected.Header = textBox;            


         //check which property is currently selected

             String parentName = ((TreeViewItem)twItemSelected.Parent).Name;
          ((TreeViewItem)twItemSelected.Parent).Parent).Name;

            //get values from file 
            //show page based on parent value
             switch (parentName)
             {
                 case "RectangleBar_TreeviewItem":
                     textBox.LostFocus += (o, ev) =>
                     {...}  
    }
1
It is strongly recommended that you create a proper ViewModel and use proper DataBinding and WPF's concepts such as DataTemplates that are intended for whatever you're trying to do rather than a winforms-like procedural approach.Federico Berasategui
Francesco is special like so, unfortunately..UIlrvnd

1 Answers

3
votes

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.

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:

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);

Please try learning and investing in the patterns and practices of WPF so that it'll be easy to do what you want to achieve.

There are also projects out there that can help you get started with what you want to achieve with TreeViews.

Sample project