0
votes

I have a TreeView. I have a contextMenu defined for the TreeViewItems.

When I right click on any TreeViewItem, I get a ContextMenu which has an option to add a new TreeViewItem under the Item on which user Right-clicked.

Here is my code:

private void AddContextMenu_Click(object sender, RoutedEventArgs e)
{
    TreeViewItem treeViewItem = null;

    foreach (TreeViewItem tvItem in StaticHelpers.FindVisualChildren<TreeViewItem>(cityTreeView))
    {
        if (tvItem.Header == ServiceLocator.Instance.SelectedCity)
        {
            treeViewItem = tvItem;
            break;
        }
    }

    AddNewCity(ServiceLocator.Instance.SelectedCity);

    treeViewItem.IsExpanded = true;

    City newlyAddedCity = getNewlyAddedCity(ServiceLocator.Instance.Cities);

    foreach (TreeViewItem tvItem in StaticHelpers.FindVisualChildren<TreeViewItem>(cityTreeView))
    {
        if (tvItem.Header == newlyAddedCity)
        {
            treeViewItem = tvItem;
            break;
        }
    }

    this.RenameContextMenu_Click(treeViewItem, e);
}

Now in the code above if I keep a breakpoint on last foreach loop, I can see that it loops through all the parent Items and those child Items whose parent's IsExpanded is set to true.

But I can also notice that when it loops through all the items, it does not get newlyAddedCity in the collection and as a result in second for loop tvItem.Header == newlyAddedCity never becomes true.

At last when the task is finished by computer I can see the newlyAddedCity in TreeView.

Update:

Here is my AddNewCity Method:

public static void AddNewCity(City parentCity)
{
    City lastAddedCity = ServiceLocator.Instance.Cities.Where(x => x.IsLastAdded == true).Select(x => x).FirstOrDefault();
    lastAddedCity.IsLastAdded = false;

    City newCity = new City()
                    {
                        Id = lastAddedCity.Id + 1,
                        IsLastAdded = true,
                        Name = "New City"
                    };

    ServiceLocator.Instance.Cities.Where(x => x.Id == parentCity.Id).FirstOrDefault().Children.Add(newCity);
    CityMethods.SaveNew(parentCity.Id, "");
}
2
So, your issue is just you could not hit the breakpoint OR facing some issue adding object to treeView? - Rohit Vats
Yes the above code just does not hit the breakpoint. No, I am not facing any issues adding object to the treeView. - Vishal

2 Answers

1
votes

TreeViewItem is an UI container which gets generated when it comes in View. In code you set IsExpanded to True but UI dispatcher didn't get time to do that processing for generating container because it's busy in executing click handler.


In case you interested in seeing item generated, you need to give UI thread some time to process it before running last foreach loop.

Invoke empty delegate on UI dispatcher with priority Render so that all delegates queued on UI dispatcher with priority higher or equal to Render gets time to execute. (UI refresh on priority Render)

Dispatcher.Invoke((Action)(() => { }), DispatcherPriority.Render);

Just place this code before your last foreach loop and you will see breakpoint gets hit.

Dispatcher.Invoke((Action)(() => { }), DispatcherPriority.Render);
foreach (TreeViewItem tvItem in StaticHelpers.FindVisualChildren<TreeViewItem>(cityTreeView))
{
    if (tvItem.Header == newlyAddedCity)
    {
        treeViewItem = tvItem;
        break;
    }
}
0
votes

the mvvm way would be to add a new item to the underlying collection and not to the treeview.

   public OberservableCollection<City> MyCollection {get;set;}

   this.MyCollection.Add(getNewlyAddedCity(ServiceLocator.Instance.Cities));

xaml

   <TreeView ItemsSource="{Binding MyCollection}"/>