How to connect to BeforeNodeExpand and AfterNodeExpand for WPF Treeview?

Intent: Displaying a busy / waiting time cursor for the entire time that the children of the node will be populated.

It seems to be hidden in WPF. I remember having some event in Winforms Tree Control where you could subscribe - to achieve this.

I currently have a TreeView that has multiple lists associated with its SelectedItem. All controls are data binding and use DataTemplates to display items. The code is functional. But when I expand the tree-node with a lot of children, the UI becomes sluggish .. it looks like the click was not registering .. and I, being an impatient user, click my mouse button on the node.

So how do I go about doing this? I would like to set the cursor to wait in BeforeExpand and reset to AfterExpand.

Scribble code:

<HierarchicalDataTemplate DataType="{x:Type local:LinqToSqlNodeClass}" ItemsSource="{Binding Path=Children}">
  // visual representation
</HierarchicalDataTemplate>
// more typed data templates 

<TreeView ItemsSource="{Binding Path=Nodes}" />

      

+3


source to share


2 answers


The ItemContainerGenerator will start generating after the Expanded event, so you can use it to set the Cursor and set it back to ItemContainerGenerator.StatusChanged to indicate that your children have been populated.

Since TreeViewItem.Expanded is a routed event, you can simply subscribe at some parent level:

myTreeView.AddHandler(TreeViewItem.ExpandedEvent, new RoutedEventHandler(TreeViewItemExpanded));

      



Where TreeViewItemExpanded is defined elsewhere, something like this:

private void TreeViewItemExpanded(object sender, RoutedEventArgs e)
{
    // we will only go through with this if our children haven't been populated
    TreeViewItem sourceItem = e.OriginalSource as TreeViewItem;
    if ((sourceItem != null)
        && (sourceItem.ItemContainerGenerator.Status != GeneratorStatus.ContainersGenerated))
    {
        // create a handler that will check our children and reset the cursor when the ItemContainerGenerator has finished
        EventHandler itemsGenerated = null;
        DateTime before = DateTime.Now;
        itemsGenerated = delegate(object o, EventArgs args)
        {
            // if the children are done being generated...
            if ((o as ItemContainerGenerator).Status == GeneratorStatus.ContainersGenerated)
            {
                (o as ItemContainerGenerator).StatusChanged -= itemsGenerated;  // we're done, so remove the handler
                sourceItem.Dispatcher.BeginInvoke(DispatcherPriority.DataBind, (ThreadStart)delegate    // asynchronous reset of cursor
                {
                    myWindow.Cursor = Cursors.Arrow;    // reset cursor
                    Debug.WriteLine("Expanded in " + (DateTime.Now - before));
                });
            }
        };
        sourceItem.ItemContainerGenerator.StatusChanged += itemsGenerated;  // add the handler
        myWindow.Cursor = Cursors.Wait;     // wait cursor
    }
    e.Handled = true;
}

      

+5


source


Edit - . The only way to achieve this is to make a class derived from TreeViewItem and override OnExpand and set up a new Expanding Routed Event before you call the underlying Expand. Then you will use this new class as your container instead of the default TreeViewItem.

Then you could do something like

<TreeView cust:CustomTreeViewItem.Expanding="TreeView_Expanding">....</TreeView>

      

Previous answer ....



The only thing I can see is Collapsed and Expanded on the TreeViewItem .

You will need to change your template to use the TreeViewItem with specific events.

Will this work for your purposes?

0


source







All Articles