【问题标题】:Select Tab Page in TabControl without stealing focus在 TabControl 中选择标签页而不窃取焦点
【发布时间】:2010-10-28 15:57:30
【问题描述】:

使用TabControl.SelectTab("...") 会显示选项卡,但它也会为选项卡提供焦点。我想显示一个特定的标签,但要保持焦点。

我在网格中有数据行。根据所选行的属性,我显示不同的标签页以具有不同的 UI 布局。但是当使用箭头键滚动行时,焦点会切换到选定的选项卡——我不希望发生这种情况。

谢谢。

【问题讨论】:

    标签: c# .net winforms


    【解决方案1】:

    您可以尝试在设置所选选项卡之前禁用TabControl,然后重新启用它。这将阻止它集中注意力。我在一个带有几个控件的选项卡控件上对此进行了测试,并没有看到任何视觉变化,但你必须在你的 UI 中尝试它,看看它是否适合你。

    tabControl1.Enabled = false;
    tabControl1.SelectTab("tabPage4");
    tabControl1.Enabled = true;
    

    为了安全起见,您可以将重新启用 TabControl 的行放在 finally 块中,以确保它不会被禁用。

    【讨论】:

    • 这是个好主意,它可以正常工作,但是启用/禁用控件的性能不是很好。原因是我的每个标签页都有很多控件,所以每一个都被禁用/启用,这会花费很多时间,并且在 UI 中看起来不太好。
    • @TheSean,我不知道是否有其他方法可以阻止它集中注意力。我认为在用户在网格中选择新行后将焦点从选项卡控件收回对您不起作用?
    • 我之前删除了我的解决方案,因为它有点 hacky/workaroundish 但可能比禁用/启用 tabcontrol 更快。如果你想试试,我取消删除它;)
    • 它确实有效,但由于我的 TabControl 中有大量控件,所以速度很慢。
    • 禁用选项卡控件会对包含的控件产生各种副作用。因此,请注意您是否调用此方法作为对来自其中一个包含控件的事件的反应。
    【解决方案2】:

    我不认为有内置函数,但你可以这样做:

    private bool skipSelectionChanged = false;
    
    private void dataGridView_SelectionChanged(object sender, EventArgs e)
    {
        if (skipSelectionChanged)
            return;
    
        // supposing we decide tab[0] has to be selected...
        this.SelectTabWithoutFocus(this.tabControl1.TabPages[0]);
    }
    
    private void SelectTabWithoutFocus(TabPage tabPage)
    {
        this.skipSelectionChanged = true;
    
        // "this" is the form in my case, so you get the current focused control
        // (ActiveControl), backup it, and re-set it after Tab activation
    
        var prevFocusedControl = this.ActiveControl;
        if (this.ActiveControl != null)
        {
            this.tabControl1.SelectedTab = tabPage;
            prevFocusedControl.Focus();
        }
        this.skipSelectionChanged = false;
    }
    

    这里,我将当前焦点控件备份,选择需要的选项卡,最后将焦点设置到原来的控件上。

    跳过布尔值是必要的,因为将焦点放在网格上会再次触发SelectionChanged 事件,导致无限循环。

    【讨论】:

    • 虽然我不认为这是一个理想的解决方案,但这个想法最终在我的应用程序中效果最好。谢谢。
    • 我不确定此解决方案是否适用于所有情况,请参阅this question
    • 我试过这个但不喜欢它,因为你看到表单闪烁到前台然后到后台。这是一个丑陋的解决方法。 Josh 的解决方案可以无缝运行。
    【解决方案3】:

    这会选择标签页,同时将焦点保持在顶部,如上文所述:

                tc.TabPages[0].Enabled = false;
                tc.SelectTab(0);
                tc.TabPages[0].Enabled = true;
    

    tc 是我的 TabControl 类型的实例(即它是我的标签控件,它有几个“标签页”)。这对我来说很有效。我的目的是用左右键(arrows) i 循环浏览这些标签页。 e.当我前进(通过Key.Right)并到达最后一个tabpage 时,我想将注意力集中在[0] 上而不激活我在该页面中的 DataGridView 以及当我后退时(通过Key.Left)并到达[0] 我想启用[tc.TabCount - 1],这是最后一个。本案例的代码为:

                tc.TabPages[tc.TabCount - 1].Enabled = false;
                tc.SelectTab(tc.TabCount - 1);
                tc.TabPages[tc.TabCount - 1].Enabled = true;
    

    完整的代码是:

        private bool KeyTc(System.Windows.Forms.Keys keyData)
        {
            if (keyData == K.Left && tc.SelectedIndex == 0)
            {
                tc.TabPages[tc.TabCount - 1].Enabled = false;
                tc.SelectTab(tc.TabCount - 1);
                tc.TabPages[tc.TabCount - 1].Enabled = true;
                return true;
            }
            else if (keyData == K.Right && tc.SelectedIndex == tc.TabCount - 1)
            {
                tc.TabPages[0].Enabled = false;
                tc.SelectTab(0);
                tc.TabPages[0].Enabled = true;
                return true;
            }
            return false;
        }
    

    这个 bool KeyTc 被返回到 switch 语句中的一个 case 中,用于关键评估:

    protected override bool ProcessCmdKey(ref Message keyMsg, Keys keyData)
        { switch keyData { ... } }
    

    【讨论】:

    • 这在本质上不是和@adrift 一样的答案吗?
    • 最好禁用单个 TabPage 而不是整个控件或手动更改窗体的焦点,因为您看不到任何闪烁的东西。这个答案应该是公认的答案。我尝试了所有答案,这一个效果最好。
    【解决方案4】:

    基于“Jeff Ogata 提出的解决方案:您可以在设置所选选项卡之前尝试禁用 TabControl,然后重新启用它。这将阻止它获得焦点”,下面是我的解决方案:

    tabMain.SelectedPageChanging += (s, e) =>
            { 
                tabMain.Enabled = false;
            };
    
            tabMain.SelectedPageChanged += (s, e) =>
            {
                tabMain.Enabled = true;                
            };
    

    注意:此代码使用 DevExpress“DevExpress.XtraTab.XtraTabControl”。

    【讨论】:

    • 最好禁用单个标签页,而不是像 Josh 所说的那样禁用整个控件。
    猜你喜欢
    • 2023-01-14
    • 2020-10-30
    • 2023-04-02
    • 2010-11-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-13
    • 1970-01-01
    相关资源
    最近更新 更多