我有绑定到对象树的树视图。当我从对象树中删除一个对象时,它已从树视图中正确删除,但是树视图的默认行为是将selecteditem跳转到已删除项目的父节点。如何更改此设置,使其跳至下一项?

编辑:

我用Aviad的建议更新了代码。这是我的代码。

public class ModifiedTreeView : TreeView
{
    protected override void OnItemsChanged(NotifyCollectionChangedEventArgs e)
    {
        base.OnItemsChanged(e);

        if (e.Action == NotifyCollectionChangedAction.Remove)
        {
            if (e.OldStartingIndex - 1 > 0)
            {
                ModifiedTreeViewItem item =
                    this.ItemContainerGenerator.ContainerFromIndex(
                    e.OldStartingIndex - 2) as ModifiedTreeViewItem;

                item.IsSelected = true;
            }
        }
    }

    protected override DependencyObject GetContainerForItemOverride()
    {
        return new ModifiedTreeViewItem();
    }

    protected override bool IsItemItsOwnContainerOverride(object item)
    {
        return item is ModifiedTreeViewItem;
    }
}

public class ModifiedTreeViewItem : TreeViewItem
{
    protected override void OnItemsChanged(NotifyCollectionChangedEventArgs e)
    {
        base.OnItemsChanged(e);

        if (e.Action == NotifyCollectionChangedAction.Remove)
        {
            if (e.OldStartingIndex > 0)
            {
                ModifiedTreeViewItem item =
                    this.ItemContainerGenerator.ContainerFromIndex(
                    e.OldStartingIndex - 1) as ModifiedTreeViewItem;

                item.IsSelected = true;
            }
        }
    }

    protected override DependencyObject GetContainerForItemOverride()
    {
        return new ModifiedTreeViewItem();
    }

    protected override bool IsItemItsOwnContainerOverride(object item)
    {
        return item is ModifiedTreeViewItem;
    }
}


除非我对其进行调试,否则上面的代码将不起作用,或者以某种方式降低OnItemsChanged方法的速度。例如,如果我将thread.sleep(500)放在OnItemsChanged方法的底部,则它可以工作,否则就不行。知道我在做什么错吗?这真是奇怪。

最佳答案

您提到的行为是由Selector类中的虚拟方法控制的,该类称为OnItemsChanged(参考:Selector.OnItemsChanged Method)-要对其进行修改,您应该从TreeView派生并重写该函数。您可以使用反射器将实现基于现有实现,尽管非常简单。

这是使用反射器提取的树视图替代TreeView.OnItemsChanged的代码:

protected override void OnItemsChanged(NotifyCollectionChangedEventArgs e)
{
    switch (e.Action)
    {
        case NotifyCollectionChangedAction.Add:
        case NotifyCollectionChangedAction.Move:
            break;

        case NotifyCollectionChangedAction.Remove:
        case NotifyCollectionChangedAction.Reset:
            if ((this.SelectedItem == null) || this.IsSelectedContainerHookedUp)
            {
                break;
            }
            this.SelectFirstItem();
            return;

        case NotifyCollectionChangedAction.Replace:
        {
            object selectedItem = this.SelectedItem;
            if ((selectedItem == null) || !selectedItem.Equals(e.OldItems[0]))
            {
                break;
            }
            this.ChangeSelection(selectedItem, this._selectedContainer, false);
            return;
        }
        default:
            throw new NotSupportedException(SR.Get("UnexpectedCollectionChangeAction", new object[] { e.Action }));
    }
}


或者,您可以从一个代码隐藏类中挂入collection NotifyCollectionChanged事件,并在事件到达TreeView之前显式更改当前选择(我不确定该解决方案,因为我不确定事件代表的调用顺序-TreeView可能要先处理事件-但可能会起作用)。

10-05 17:41