WPF TabControl - 无法以编程方式选择选项卡

发布于 2024-11-10 00:13:42 字数 1522 浏览 2 评论 0原文

我有一个带有 TabControl 的用户界面,最初显示一个起始页。例如,可以通过双击 DataGrid 中的内容来将其他项目添加到其中。新选项卡应在创建时选择。如果与网格中的项目相对应的文档已打开,则应打开该文档的现有选项卡,而不是创建新选项卡。

我知道我应该能够通过设置 TabControl 的 SelectedItem 或 SelectedIndex 属性以编程方式选择选项卡。然而,所需的选项卡从未真正激活。如果我设置一个,然后在调试器中检查 TabControl 的状态,那么这两个字段似乎都会正确更新。但是,在继续执行后,我看到所选选项卡在 UI 中保持不变,如果我暂停并再次检查 TabControl 的状态,我会看到 SelectedItem 和 SelectedIndex 已返回到之前的值。另一方面,通过在 UI 中单击选项卡来选择选项卡则效果很好。

这是 TabControl 的声明:

<TabControl x:Name="Tabs" >
    <TabItem x:Name="StartPageTab" Header="Start Page" DataContext="{Binding Path=StartPageViewModel}">
        ...
    </TabItem>
</TabControl>

以及添加和选择选项卡的代码:

private void _SelectTab(MyViewModel model)
{
    TabItem tab;
    if (_TryFindTab(model, out tab)) Tabs.SelectedItem = tab;
}

private bool _TryFindTab(MyViewModel target, out TabItem tab)
{
    foreach (TabItem item in Tabs.Items)
    {
        MyViewModel model = item.DataContext as MyViewModel;
        if (model != null && model.Equals(target))
        {
            tab = item;
            return true;
        }
    }
    tab = null;
    return false;
}

private void _AddTab(MyViewModel model)
{
    TabItem tab = new TabItem { DataContext = model, Content = new MyView() };
    Binding bind = new Binding { Source = model, Path = new PropertyPath("Name") };
    tab.SetBinding(TabItem.HeaderProperty, bind);

    Tabs.Items.Add(tab);
    Tabs.SelectedItem = tab;
}

I have a user interface with a TabControl that initially displays a start page. Other items can be added to it by double-clicking on content in, for example, a DataGrid. New tabs should be selected when they are created. If the document corresponding to the item in the grid is already open, then the existing tab for that document should be opened rather than creating a new one.

I know that I should be able to programmatically select a tab by setting the TabControl's SelectedItem or SelectedIndex properties. However, the desired tab never actually activates. If I set one and then inspect the TabControl's state in the debugger, then both fields seem to update properly. However, after I continue execution, I see that the selected tab remains unchanged in the UI, and if I pause and inspect the TabControl's state again I see that the SelectedItem and SelectedIndex have returned to their previous values. Selecting a tab by clicking on it in the UI, on the other hand, works just fine.

Here's the declaration for the TabControl:

<TabControl x:Name="Tabs" >
    <TabItem x:Name="StartPageTab" Header="Start Page" DataContext="{Binding Path=StartPageViewModel}">
        ...
    </TabItem>
</TabControl>

And the code for adding and selecting tabs:

private void _SelectTab(MyViewModel model)
{
    TabItem tab;
    if (_TryFindTab(model, out tab)) Tabs.SelectedItem = tab;
}

private bool _TryFindTab(MyViewModel target, out TabItem tab)
{
    foreach (TabItem item in Tabs.Items)
    {
        MyViewModel model = item.DataContext as MyViewModel;
        if (model != null && model.Equals(target))
        {
            tab = item;
            return true;
        }
    }
    tab = null;
    return false;
}

private void _AddTab(MyViewModel model)
{
    TabItem tab = new TabItem { DataContext = model, Content = new MyView() };
    Binding bind = new Binding { Source = model, Path = new PropertyPath("Name") };
    tab.SetBinding(TabItem.HeaderProperty, bind);

    Tabs.Items.Add(tab);
    Tabs.SelectedItem = tab;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

岁吢 2024-11-17 00:13:42

事实证明,它与我在原始问题描述中方便地省略的一些内容有关:

有问题的 DataGrid 位于 StartPageTab 的内容中。我通过捕获其 MouseDoubleClick 事件来处理对该 DataGrid 的双击,搜索可视化树以查找双击的 DataGridRow(如果有),然后引发一个最终将由主窗口捕获的事件,该事件将做出响应通过调用 _SelectTab 或 _AddTab,具体取决于相关文档是否已打开。

此时,调用堆栈将展开并返回到 MouseDoubleClick 事件处理程序。在该处理程序中,我忘记将 MouseButtonEventArgs 的 Handled 属性设置为 true。因此,WPF 不断寻找其他人来处理该单击事件 - 最终找到的元素将通过请求焦点来响应,这反过来意味着原始选项卡需要重新获得焦点。

添加 e.Handled = true; 阻止了整个混乱,因此新选项卡可以保持选中状态。

It turned out to be related to something I conveniently omitted from the original problem description:

The DataGrid in question was in the content for StartPageTab. I was handling double-clicks on that DataGrid by capturing its MouseDoubleClick event, searching the visual tree to find what DataGridRow was double-clicked (if any), and then raising an event that would eventually be captured by the main window, which would respond by calling either _SelectTab or _AddTab, depending on whether the document in question was already open.

At which point, the call stack would unroll and get back to that MouseDoubleClick event handler. In that handler, I forgot to set the MouseButtonEventArgs's Handled property to true. So WPF kept searching for someone else to handle that click event - and the element that it eventually found would respond by asking for focus, which in turn meant that the original tab needed to get focus back.

Adding e.Handled = true; stopped that whole mess in its tracks, so the new tab could stay selected.

心意如水 2024-11-17 00:13:42

您可以尝试使用 tab.focus()

我的应用程序中有选项卡,这是使您选择的选项卡可见的快速方法。

You could try using tab.focus()

I have tabs in my application and this is a quick way to make your selected tab visible.

太阳男子 2024-11-17 00:13:42

您是否尝试过绑定到 TabItem.IsSelected 并在您的视图模型中更新它?

Have you tried binding to TabItem.IsSelected and updating that in you view model?

删除→记忆 2024-11-17 00:13:42

在我使用的旧 C# 应用程序中,使用页面控件,我能够通过告诉选项卡控件对象选择选项卡来强制页面处于活动状态...

MyTabControlWithMultiplePages.SelectTab(PageIWantShown);

In an older C# app I had, using page controls, I was able to force the page active by telling the tab control object to select the tab...

MyTabControlWithMultiplePages.SelectTab(PageIWantShown);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文