【问题标题】:Design Custom TabPage in C# WinForms?在 C# WinForms 中设计自定义 TabPage?
【发布时间】:2012-03-21 01:39:08
【问题描述】:

我有一个 c# WinForm 应用程序,我需要在运行时生成 TabPages。理想情况下,我想使用 VS 设计器设计这些标签页,但似乎我不能直接这样做,因为我不能从工具箱中拖放它(还有其他方法吗?)。

我有两个通用标签页,我将多次使用它们。一个包含一个简单的电子表格和几个文本框,另一个包含一个图表和几个文本框。这些页面最终会变得更加复杂。我正在寻找这样做的最佳方法。我目前只是为每个标签页创建自定义类并将其设置为 TabPage 基类。例如:

public partial class SpreadsheetTabPage : TabPage{} 

我读到用户控件提供了某种形式的替代方案,但我并不真正了解使用它与我的方法相比的优势。

所以要明确一点,我想知道您认为开发这些自定义标签页的最佳方法是什么以及为什么。如果相关,请提供基本代码示例。我的方法并没有真正引起太多问题,但我发现以后向这些页面添加内容会很困难,尤其是在不使用设计器的情况下。

提前感谢您的帮助!

【问题讨论】:

  • 在 TabControl 的属性窗口中有一个 TabPages 属性,您可以在其中添加任何您喜欢的标签页
  • 你可以添加一个 tabcontrol 和 tabpages 给它,但实际上并不看它的设计。这与仅在自己的类中编码并像上面那样手动设置属性没有什么不同。

标签: c# winforms user-controls tabs


【解决方案1】:

如果您创建一个包含您的 tabcontrol 的用户控件,您可以看到设计器并根据需要进行设计,您可以添加一些额外的代码,并且仍然可以将其从工具箱中拖放以使用它。

注意:在你重建你的项目之前,你看不到你的用户控制(你的手动编码的类)

【讨论】:

  • 你的想法似乎是对的。我做了这个略有不同,但我会给你答案。我制作了一个自定义用户控件并将其手动添加到标签页中。感谢您的注意,也为我节省了一些谷歌搜索:)
【解决方案2】:

您可以创建自己的 TabControl 设计器,并在设计时实现您需要的功能。以下是此类设计器最简单版本的代码:

using System;
using System.Drawing;
using System.Collections;
using System.Windows.Forms;
using System.Windows.Forms.Design;
using System.ComponentModel.Design;
using CustomTabControlExample.TabControl;

namespace CustomTabControlExample.Design {
    public class CustomTabControlDesigner :ParentControlDesigner {
        DesignerVerbCollection fVerbs;
        public override DesignerVerbCollection Verbs {
            get {
                if (fVerbs == null)
                    fVerbs = new DesignerVerbCollection(new DesignerVerb[] {
                        new DesignerVerb("Add Tab", OnAdd)
                        });
                return fVerbs;
            }
        }

        void OnAdd(object sender, EventArgs e) {
            TabPage newPage = (TabPage)((IDesignerHost)GetService(typeof(IDesignerHost))).CreateComponent(
                typeof(CustomTabPage));
            newPage.Text = newPage.Name;
            ((System.Windows.Forms.TabControl)Component).TabPages.Add(newPage);
        }

        public override void InitializeNewComponent(IDictionary defaultValues) {
            base.InitializeNewComponent(defaultValues);
            for (int i = 0; i < 2; i++)
                OnAdd(this, EventArgs.Empty);
        }

        protected override void WndProc(ref Message m) {
            base.WndProc(ref m);
            // Selection of tabs via mouse
            if (m.Msg == 0x201/*WM_LBUTTONDOWN*/) {
                System.Windows.Forms.TabControl control = (System.Windows.Forms.TabControl)Component;
                int lParam = m.LParam.ToInt32();
                Point hitPoint = new Point(lParam & 0xffff, lParam >> 0x10);
                if (Control.FromHandle(m.HWnd) == null) // Navigation
                    if (hitPoint.X < 18 && control.SelectedIndex > 0) // Left
                        control.SelectedIndex--;
                    else control.SelectedIndex++; // Right
                else // Header click
                    for (int i = 0; i < control.TabCount; i++)
                        if (control.GetTabRect(i).Contains(hitPoint)) {
                            control.SelectedIndex = i;
                            return;
                        }
            }
        }

        protected override void OnDragDrop(DragEventArgs de) {
            ((IDropTarget)((System.Windows.Forms.TabControl)Component).SelectedTab).OnDragDrop(de);
        }

        protected override void OnDragEnter(DragEventArgs de) {
            ((IDropTarget)((System.Windows.Forms.TabControl)Component).SelectedTab).OnDragEnter(de);
        }

        protected override void OnDragLeave(EventArgs e) {
            ((IDropTarget)((System.Windows.Forms.TabControl)Component).SelectedTab).OnDragLeave(e);
        }

        protected override void OnDragOver(DragEventArgs de) {
            ((IDropTarget)((System.Windows.Forms.TabControl)Component).SelectedTab).OnDragOver(de);
        }
    }
}

这似乎是一个相当复杂的方法,但是一旦你学会了它,你就会对 Visual Studio 提供的强大功能印象深刻。您可以在 MSDN 中找到很多信息。以下描述了最常见的功能:Enhancing Design-Time Support

【讨论】:

    【解决方案3】:

    我遇到这个帖子时也想到了同样的问题。在考虑了这个问题后,我意识到解决方案正盯着我的脸。它实际上非常基本和优雅。

    我所做的是创建了一个名为 TabPageLibrary 的用户控件。因此,我在其上拖动了一个 TabControl,并根据我想要的设置添加了页面。然后我将 TabPage 修饰符设置为内部。当我需要特定的扩展 TabPage 时 - 我只需调用 TabPageLibrary 类并获取特定应用程序所需的 TabPage。这使我能够在整个 winform 应用程序中重用特定的预配置 TabPage

    private void PropertiesButton_Click(object sender, EventArgs e)
    {
    TabPageLibrary library = new TabPageLibrary();
    TabPage propertyPage = library.PropertyPage;
    this.tabControl.TabPages.Add(propertyPage);
    }
    

    这当然解决了我的问题——也许它适用于您的应用程序。

    【讨论】:

    • 这正是我要寻找的!谢谢你的回答。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-01-24
    • 2011-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多