如何为WPF Treeview挂钩BeforeNodeExpand和AfterNodeExpand?

时间:2009-01-06 13:53:09

标签: wpf treeview

意图:在填充节点子节点的持续时间内显示忙/等光标。

似乎隐藏在WPF中。我记得在Winforms Tree Control中有一些你可以订阅的事件 - 为了达到这个目的。

目前我有一个TreeView,它有许多与其SelectedItem相关联的列表视图。所有控件都是数据绑定,并使用DataTemplates显示项目。代码是有用的。 但是当我扩展一个有很多孩子的树节点时,用户界面变得缓慢......看起来点击没有注册..我是一个不耐烦的用户去点击节点点击。

那我该怎么做?我想在AfterExpand中将Cursor设置为Wait并在AfterExpand中重置。

Code Scribble:

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

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

2 个答案:

答案 0 :(得分:5)

ItemContainerGenerator将在Expanded事件之后开始生成,因此您可以使用它来设置Cursor,并在ItemContainerGenerator.StatusChanged触发后将其设置回来,以指示您的孩子已被填充。

由于TreeViewItem.Expanded是路由事件,您只能在某个父级别订阅:

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

TreeViewItemExpanded在其他地方定义,如下所示:

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

答案 1 :(得分:0)

编辑 - 实现此目的的唯一方法是创建一个派生自TreeViewItem的类,并在调用基础展开之前覆盖OnExpand并设置新的扩展路由事件。然后,您将使用此新类作为容器,而不是默认的TreeViewItem。

然后你可以做类似

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

以前的答案....

我可以看到您使用的唯一内容是Collapsed上的ExpandedTreeViewItem事件。

您必须更改模板以使用TreeViewItem,并定义事件。

这是否适用于您的目的?