【问题标题】:Changing selection of TabControl programatically works for content, but not for tab/header以编程方式更改 TabControl 的选择适用于内容,但不适用于选项卡/标题
【发布时间】:2015-05-20 10:24:27
【问题描述】:

我有一个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 和所有后续选项卡会取消选择所有选项卡,同时显示来自最近添加的。

【问题讨论】:

    标签: c# wpf tabcontrol selecteditem selectedindex


    【解决方案1】:

    这里发生了一些错误。

    MyCollection_CollectionChanged 方法位于 View 的代码隐藏(.xaml.cs 文件)中,而不是 ViewModel 中。使用 Snoop 工具 (snoopwpf.codeplex.com),我能够确定索引以某种方式设置超出范围。例如,如果我添加了第 4 项,该项目将被放置在索引 3 处,我会尝试更改为该索引。我的控制台日志消息会说所选索引已成功更改为 3,但是 Snoop 工具会说索引为 4(!),而所有四个选项卡似乎都在后台。真是奇怪。其他集合对象可能会抛出超出范围的异常,但此 TabControl 不会。

    当我发现这个非一错误时,我试图将索引设置为不是实际索引,而是索引减一。结果不是修复,而是预期的行为。如果我尝试将索引设置为应有的值,它将落在 index + 1 上,但如果我尝试将其设置为 index - 1,它实际上会将其更改为 index - 1。这意味着我永远无法定位所需的选项卡,但总是向左移动一个,或向右移动一个(超出范围)。

    我没有使用 View 的代码隐藏从 NotifyCollectionChangedEventArgs 中挖掘 MyClass 对象,以便它可以用于更改选项卡(这可能首先违反 MVVM 模式),而是决定使用 ViewModel 来更改标签。这意味着将 TabControl 传递给 ViewModel,以便它可以添加到集合中,然后立即更改下一行代码的选项卡,如下所示:

    MyCollection.Add(newThing);
    _tabControl.SelectedItem = newThing;
    

    像魅力一样工作!如果您看到没有选择选项卡的 TabControl,请记住此修复。索引更改可能发生在错误的线程中,或者类似的事情。

    【讨论】:

      猜你喜欢
      • 2018-10-22
      • 2011-09-01
      • 2022-01-07
      • 2015-10-06
      • 2021-02-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多