我有一个ListView
,允许我选择项目,然后将其添加到ObservableCollection
。此ObservableCollection
绑定到TabControl
,因此我在添加项目时会收到新标签。我想要的是每个新选项卡被选中并自动显示其内容。
从内容的角度来看,这是有效的。我可以按预期看到新添加的项目内容,但是从TabControl
本身的外观来看,所有标签都被取消选中,"或移到后台。
以下是我正在做的事情:(请注意,我设置了SelectedItem。设置SelectedIndex或SelectedValue时,我会遇到类似的结果。不确定这里最好的是什么。)
void MyCollection_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.Action == NotifyCollectionChangedAction.Add)
{
List<MyClass> newStuff = e.NewItems.Cast<MyClass>().ToList<MyClass>();
if (newStuff.Count == 1)
myTabControl.SelectedItem = newStuff[0];
}
}
使用Console.WriteLine
和TabControl的SelectionChanged事件,我可以验证TabControl.SelectedIndex
是否按预期更改。但是,对于每个新项目,所有选项卡似乎都会移动到后台。
我总是看到新项目的内容,但我必须手动点击该标签,以便它可视地显示为前景标签。
每当我单击应该已经位于前台的后台选项卡时,我的控制台通常会显示冗余调试消息。
例如,如果我从集合中的零项目开始然后添加一项,我会得到一个背景标签,一个控制台消息,然后我会看到该项目的内容。如果我单击选项卡,它会到达前台并且SelectionChanged方法触发(!!!),在我凝视相同的项目内容时重复相同的控制台消息:
myTabControl now has SelectedIndex of 0
myTabControl now has SelectedIndex of 0
如何以编程方式显示新标签的内容,并将该标签视为前景标签?
我可以通过设置myTabControl.SelectedIndex = -1
以编程方式将任意标签带到前台的唯一方法。显然,当ObservableCollection
包含项目时,这不是一个选项,因此这会强制TabControl
将第一个标签(内容,标题和所有标签)移动到前台。我在这里缺少什么?
更正:使用此方法(设置SelectedItem
)我确实在前台获得了第一个标签,但是创建标签#2并且所有后续标签取消选择所有标签,同时显示来自最近添加的内容。
答案 0 :(得分:0)
这里发生了一些一对一的错误。
方法MyCollection_CollectionChanged位于我的View代码隐藏(.xaml.cs文件)中,而不是ViewModel中。使用Snoop工具(snoopwpf.codeplex.com),我能够确定索引是以某种方式设置为超出范围。例如,如果我添加了项目#4,该项目将被放置在索引3处,我将尝试更改为此索引。我的控制台日志消息会说所选索引已成功更改为3,但是Snoop工具会说索引为4(!),而所有四个选项卡似乎都在后台。真奇怪。其他集合对象可能会抛出超出范围的异常,但不会抛出此TabControl。
当我发现这个一个一个错误时,我试图将索引设置为不是实际索引,而是设置索引减一。结果不是修复,而是预期的行为。如果我试图将索引设置为它应该是什么,它将落在索引+ 1上,但如果我尝试将其设置为索引-1,它实际上会将其更改为索引 - 1.这意味着我永远无法定位所需的索引选项卡,但始终向左或向右(超出范围)。
我没有使用View的代码隐藏来从NotifyCollectionChangedEventArgs挖出MyClass对象,以便它可以用来更改标签(这可能首先违反了MVVM模式),我决定使用用于更改选项卡的ViewModel。这意味着将TabControl传递给ViewModel,以便它可以添加到集合中,然后立即更改下一行代码的选项卡,如下所示:
MyCollection.Add(newThing);
_tabControl.SelectedItem = newThing;
像魅力一样!如果您看到没有选中选项卡的TabControl,请记住此修复。索引更改可能发生在错误的线程或某些此类事情中。