我有绑定到对象树的树视图。当我从对象树中删除一个对象时,它已从树视图中正确删除,但是树视图的默认行为是将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
可能要先处理事件-但可能会起作用)。