【问题标题】:custom control design-time自定义控件设计时
【发布时间】:2013-03-04 09:36:58
【问题描述】:

我想创建自己的带有设计时支持的 TabControl 类。

这是我的设计师:

public class TabListDesigner : ParentControlDesigner
{
    protected TabList TabListControl { get { return this.Control as TabList; } }

    protected override void WndProc(ref Message m)
    {
        switch (m.Msg)
        {
            case 0x7b: // WM_CONTEXTMENU
                this.OnContextMenu(Cursor.Position.X, Cursor.Position.Y);
                break;
            default:
                base.WndProc(ref m);
                break;
        }
    }

    protected override bool GetHitTest(Point point)
    {
        return this.TabListControl.HitTest(this.TabListControl.PointToClient(point)) != null;
    }

    protected override void OnPaintAdornments(PaintEventArgs pe)
    {
        base.OnPaintAdornments(pe);
        ControlPaint.DrawFocusRectangle(pe.Graphics, this.Control.ClientRectangle);
    }

    public override void InitializeNewComponent(IDictionary defaultValues)
    {
        base.InitializeNewComponent(defaultValues);
        this.AddTabListPage();
        this.AddTabListPage();
    }

    protected virtual void AddTabListPage()
    {
        IDesignerHost host = (IDesignerHost)this.GetService(typeof(IDesignerHost));

        if (host != null)
        {
            using (DesignerTransaction transaction = host.CreateTransaction(string.Format("Add TabListPage to '{0}'", this.TabListControl.Name)))
            {
                try
                {
                    TabListPage page = (TabListPage)host.CreateComponent(typeof(TabListPage));
                    MemberDescriptor controlsProperty = TypeDescriptor.GetProperties(this.TabListControl)["Controls"];

                    this.RaiseComponentChanging(controlsProperty);

                    this.TabListControl.Add(page);
                    this.TabListControl.Controls.Add(page);

                    this.RaiseComponentChanged(controlsProperty, null, null);

                    transaction.Commit();
                }
                catch
                {
                    transaction.Cancel();
                    throw;
                }
            }
        }
    }
}

在设计器中,我将 Tabcontrol 添加到表单中,并且 2 个 TabPages 正确显示。现在我测试项目,2 个标签页消失了。我回到设计师那里,标签页已经不存在了。为什么?

【问题讨论】:

  • 您是否尝试过将环境设置为debug your design time controls? 能够像往常一样单步执行代码,如果您遵循流程,可以很好地突出问题。
  • 我认为问题出在序列化上。您的示例在开头创建了一个带有 2 个选项卡的 TabList,但是这两个选项卡没有被序列化。检查表单头文件中的“#pragma region Windows 窗体设计器生成的代码”区域。如果你找不到 TabList->Items->Add(TabPage1);然后你的页面被序列化了。
  • 我不知道,但我觉得有一点很奇怪:您先将同一页面添加到 TabListControl,然后再添加到 TabListControl.Controls。

标签: c# .net winforms


【解决方案1】:

我曾经创建了一个控件设计器,不是表单设计器使用的,而是更像是单个控件的实际表单设计器。我不记得该项目的太多内容,但我确实记得遇到过完全相同的问题,并且我不得不提醒 Visual Studio 我以某种方式更改了值。

保存设计器选项卡后,Visual Studio 将继续根据语言将该更改转换为代码,并将其写入表单的设计器文件中。您还可以使用 codeDom 编写自己的特定代码生成器,但这是非常先进的。

这不是你想要的,但我敢打赌这个问题是相关的,所以请耐心等待。我能在现场找到的唯一例子是一个古老的 c# 项目,叫做“Shape Designer”之类的。我从一个浅蓝色的网站上得到它。我做了一些搜索,但我无法找到该页面。无论如何,代码有据可查,他非常透彻地解释了你的问题。

我也有我的项目,这是一个标签式的东西,当你转到另一个页面时,它会在页面之间进行动画处理。它在 vb.net 中,没有很好的文档记录,但您可能想一睹它的风采。

Here's the project, here's a image of the designer 和一个 animated gif of the end result

编辑:

在我的项目中,在“DesignerControl.vb”文件的第 187 行:

' The controldesigner don't always save properties which are changed directly :/
Private Sub SetValue(itm As Item, pName$, val As Object)
    Dim Prop As PropertyDescriptor = TypeDescriptor.GetProperties(itm.Page)(pName)
    If Prop IsNot Nothing AndAlso Prop.PropertyType Is val.GetType Then Prop.SetValue(itm.Page, val)
End Sub

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-21
    • 1970-01-01
    • 2010-12-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多