如何在 TabPage header 旁边显示 ErrorProvider 错误图标?

How to show an ErrorProvider error icon next to a TabPage header?

编辑: 这不是 Icons in TabControl C# - How? 的副本。那里的问题是关于将图标添加到标签页。这里是关于如何将错误提供程序错误图标位置更改为 header 内而不是标签页本身的右侧。此外,错误提供程序错误图标具有以下功能:当您将鼠标悬停在其上时,您会看到错误文本,如果您只是将图标添加到 header.

则看不到错误文本

我有一个带有 TabControl 的表格。该表格还有一个 ErrorProvider。当我尝试使用以下代码时:

errorProvider1.SetError(tabPage1, "error");

错误图标显示在选项卡页面的右侧,由选项卡控件本身 cut-off 显示:

我希望图标显示在标签页旁边 header。像这样的东西(用 Photoshop 制作):

我不知道从哪里开始,也不知道如何处理。

编辑: 我有一个 class 负责向控件添加错误,并使用错误提供程序显示它们。此 class 用于 TextBoxes、NumericUpDowns 等。我也想将它用于 TabPages。问题是,当我将它用于标签页时,会得到如上所示的结果。使用 ImageList 将错误图标添加到 header 然后添加工具提示的技巧并不好,因为它特定于标签页,我无法在我的 class 中实现它这对所有控件都是通用的。所以我真的需要更改标签页的设置,所以当我使用 errorProvider.SetError(...) 它显示在 header.

您可以执行以下操作。

Rectangle rc = tabControl1.GetTabRect(0); // Replace with the index of Tab required
errorProvider1.SetIconPadding(tabControl1, -rc.Left-20);;
errorProvider1.SetError(tabControl1, "Error String");

您还需要设置

errorProvider1.SetIconAlignment(tabControl1, ErrorIconAlignment.TopLeft);

示例(选择了第二个选项卡 - 基于评论),

您需要在 TabPage 文本前添加白色space 以确保有足够的 space 来显示图标

在第二个选项卡上有图标

ErrorProvider 在标签页的客户区显示 TabPage 的错误图标。 通过使用 IconAlignmentIconPadding,您可以在其中一个标签页的 headers 上显示 TabControl 的错误图标,但它是整个 TabControl 的错误图标].

在实际应用程序中,每个标签页都可以包含无效控件,您可能希望在标签页上显示验证图标而不是针对标签控件。

我的建议是通过将包含错误图标的 ImageList 设置为 TabControl 的图像列表并通过设置 TabPageImageIndex 来使用标签页图标,显示或隐藏图像图标。这样你就可以为每个需要它的标签页显示错误图标:

例子

要设置示例,请按照下列步骤操作:

  1. 创建 Form.
  2. Form 上放置一个 TabControl、一个 ErrorProvider 和一个 ImageList
  3. tabControl1ImageList 属性 设置为 imageList1
  4. tabPage1 上放置两个 TextBox
  5. 我假设,例如,您将使用 Validating 事件来验证这两个文本框控件。关键点就在这里。当您验证任何控件时,检查它是否托管在 TabPage 中,检查 TabPage 的所有 children 的有效性并基于此设置错误图标:

    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);
        this.AutoValidate = AutoValidate.EnableAllowFocusChange;
        imageList1.ColorDepth = ColorDepth.Depth32Bit;
        imageList1.Images.Add(errorProvider1.Icon);
        tabControl1.ImageList = imageList1;
        textBox1.Validating += textBox_Validating;
        textBox2.Validating += textBox_Validating;
    }
    private void textBox_Validating(object sender, CancelEventArgs e)
    {
        var textBox = (TextBox)sender;
        if (string.IsNullOrEmpty(textBox.Text))
        {
            this.errorProvider1.SetError(textBox, "Value is required.");
            e.Cancel = true;
        }
        else
            this.errorProvider1.SetError(textBox, null);
        var tabPage = textBox.Parent as TabPage;
        if (tabPage != null)
            ValidateTabPage(tabPage);
    }
    void ValidateTabPage(TabPage tabPage)
    {
        var tabIsValid = tabPage.Controls.Cast<Control>()
            .All(x => string.IsNullOrEmpty(errorProvider1.GetError(x)));
        if (tabIsValid)
            tabPage.ImageIndex = -1;
        else
            tabPage.ImageIndex = 0;
    }