我有一个TabControl,我正在以编程方式向其中添加Tabpages.

TabPage1
   UserControl1
      TextBox1, TextBox2, TextBox3
TabPage2
   UserControl2
      TextBox4, TextBox5, TextBox6

现在,我希望每当用户更改选项卡时,当再次 Select 选项卡时,该选项卡以前聚焦的控件再次获得焦点.

例子:

  1. 假设重点是TabPage1→ 用户控制1→ 文本框2
  2. 然后我点击标签页2→用户控制2→文本框4
  3. 然后我再次点击TabPage1,我想让TextBox2获得焦点.

我该怎么办?

推荐答案

可能的解决方案:

Override UpdateDefaultButton() in your Form; this method is called each time a Control becomes the ActiveControl.
Of course, if you have UserControls inside TabPages, the ActiveControl is the UserControl, but you need its child Control that is currently focused.

在示例代码中,我使用GetFocus()函数获取聚焦控件的句柄,然后使用Control.FromHandle()获取带有该句柄的控件实例,如果不是null,则将该信息与当前选项卡页一起存储在字典中.

When the TabControl's Selected event is raised, check whether the Dictionary has stored the new current TabPage and, if a Control is associated with that TabPage, move the focus on it.
(I'm using BeginInvoke() because we're changing the ActiveControl in the Selected handler, which would in turn cause a call to UpdateDefaultButton())

  • 注意,这里我并不是在验证聚焦控件是否是TabPage之外的其他容器的子容器:如果TabPage中有嵌套的容器,则需要一个递归方法来判断祖先之一是否是TabPage.
Private tabPagesActiveControl As New Dictionary(Of Integer, Control)

Protected Overrides Sub UpdateDefaultButton()
    MyBase.UpdateDefaultButton()
    If ActiveControl Is Nothing Then Return

    If TypeOf ActiveControl.Parent Is TabPage Then
        Dim tp = DirectCast(ActiveControl.Parent, TabPage)
        Dim tabPageIdx = DirectCast(tp.Parent, TabControl).SelectedIndex
        Dim ctl = FromHandle(GetFocus())

        If ctl IsNot Nothing Then
            If tabPagesActiveControl.Count > 0 AndAlso tabPagesActiveControl.ContainsKey(tabPageIdx) Then
                tabPagesActiveControl(tabPageIdx) = ctl
            Else
                tabPagesActiveControl.Add(tabPageIdx, ctl)
            End If
        End If
    End If
End Sub

Private Sub TabControl1_Selected(sender As Object, e As TabControlEventArgs) Handles TabControl1.Selected
    Dim ctl As Control = Nothing
    If tabPagesActiveControl.TryGetValue(e.TabPageIndex, ctl) Then
        BeginInvoke(New Action(Sub() ctl.Focus()))
    End If
End Sub

Win32函数声明:

<DllImport("user32.dll", CharSet:=CharSet.Auto)>
Friend Shared Function GetFocus() As IntPtr
End Function

C# Version:

private Dictionary<int, Control> tabPagesActiveControl = new Dictionary<int, Control>();

protected override void UpdateDefaultButton()
{
    base.UpdateDefaultButton();
    if (ActiveControl is null) return;

    if (ActiveControl.Parent is TabPage tp) {
        var tabPageIdx = (tp.Parent as TabControl).SelectedIndex;
        var ctl = FromHandle(GetFocus());
        if (ctl != null) {
            if (tabPagesActiveControl.Count > 0 && tabPagesActiveControl.ContainsKey(tabPageIdx)) {
                tabPagesActiveControl[tabPageIdx] = ctl;
            }
            else {
                tabPagesActiveControl.Add(tabPageIdx, ctl);
            }
        }
    }
}

private void tabControl1_Selected(object sender, TabControlEventArgs e)
{
    if (tabPagesActiveControl.TryGetValue(e.TabPageIndex, out Control ctl)) {
        BeginInvoke(new Action(() => ctl.Focus()));
    }
}

Win32函数声明:

[DllImport("user32.dll", CharSet = CharSet.Auto)]
internal static extern IntPtr GetFocus();

This is how it works:
Note: TabPage2 and TabPage3 contain the instance of a UserControl with 2 TextBoxes and a ListBox. TabPage1 contains a TextBox and a NumericUpDown.

TabControl TabPage restore ActiveControl

Csharp相关问答推荐

将C#字符串转换为其UTF8编码字符的十六进制表示

C# Json重新初始化动态类型

HttpContext. RequestAborted当Android APP失go 连接时未取消

解析需要HttpClient和字符串的服务

始终保留数组中的最后N个值,丢弃最老的

属性getter和setter之间的空性不匹配?

Unity 2D自顶向下弓旋转

如果属性名为xyz,我需要使用System.Text.Json修改字符串类型的值""<>

System.Net.Http.HttpClient.SendAsync(request)在docker容器内的POST方法30秒后停止

如何在C#中使用Postman中的本地IP向本地主机上运行的本地API发出请求

在此系统上已禁用获取正在运行的脚本.&在ASP.NET Core Web API中

在.NET 8最低API中从表单绑定中排除属性

BFF到具有AAD/Entra ID B2C的内部API(.NET/ASP.NET核心/标识.Web)

同一组件的多个实例触发相同的事件处理程序

为什么此名称不再被识别?名称不存在于当前上下文中?

Azure Functions v4中的Serilog控制台主题

为什么Azure函数(独立工作进程)索引失败?使用Azure App配置的CosmosDbTrigger绑定失败,未解析为值

从MudAutoComplete打开对话框,列表仍然可见

SqlException:无法打开数据库.升级到Dotnet 8后-数据库兼容性版本-非EFCore兼容性级别

通过mini kube中的远程调试Pod与从emoteProcessPickerScript中解析错误输出的代码错误进行比较