从工具箱拖动控件时,ControlDesigner未处于活动状态

3

我正在尝试为我的自定义WinForms控件添加设计师支持,但看起来只有在我已经创建了实例时,设计师才处于活动状态,而不是在从工具箱拖放期间。

为了说明我的意思,我创建了一个简单的带有设计师的控件:

[Designer(typeof(MyButtonDesigner))]
public class MyButton:Button
{
    public MyButton()
    {
        base.Size= new Size(50,50);
    }
}
class MyButtonDesigner : ControlDesigner
{
    public override bool CanBeParentedTo(IDesigner parentDesigner)
    {
        return parentDesigner != null && parentDesigner.Component is Form;
    }
}

我希望我的控件只能由表单托管(用户只能将控件添加到表单,而不能添加到groupbox中)。 当我从工具箱拖动控件时,我的验证逻辑被跳过,但是当我尝试将控件实例从表单移动到groupbox时,我可以看到下拉菜单已经通过验证(如下图所示)。

enter image description here

我对ControlDesigner非常陌生,因此我不确定这种行为是否是设计问题,还是我可以更改它,以便在从工具箱拖动时进行验证。
我正在使用Visual Studio 2013,但我认为这不应该是问题。
1个回答

3
从工具箱拖动项目到设计表面时,CanBeParentedTo方法不会被调用。
您可以为控件创建自定义ToolBoxItem,然后重写CreateComponentsCore方法,以在父级不是Form时防止创建控件。当从工具箱拖动控件时将使用ToolBoxItem,而当从设计表面拖动控件时将使用Designer
//Add reference to  System.Drawing.dll then using
using System.Drawing.Design;
using System.Windows.Forms.Design;
public class MyButtonToolBoxItem:ToolboxItem
{
    protected override IComponent[] CreateComponentsCore(IDesignerHost host,
        System.Collections.IDictionary defaultValues)
    {
        if(defaultValues.Contains("Parent"))
        {
            var parent = defaultValues["Parent"] as Control;
            if(parent!=null && parent is Form)
                return base.CreateComponentsCore(host, defaultValues);
        }

        var svc = (IUIService)host.GetService(typeof(IUIService));
        if (svc != null) svc.ShowError("Can not host MyButton in this control");

        return null;
    }
}

要为您的控件注册工具箱项:

[ToolboxItem(typeof(MyButtonToolBoxItem))]
[Designer(typeof(MyButtonDesigner))]
public class MyButton : Button

因此,当您从工具箱拖动控件并将其放置在除窗体以外的任何容器上时,它会向用户显示一条消息,并且不会添加到该父级。如果您愿意,可以删除消息框。


非常感谢,我从未使用过ToolboxItem类,这是我必须了解的内容。除了一件事情外,一切都正常。当我将项目从工具箱拖到表单之外的其他地方时,它不会被添加(如预期),但鼠标指针仍然表明我可以在那里放置它。我能否将光标更改为“否”,因为现在有点令人困惑-用户看到他可以放置控件,但实际上我正在阻止它。 - Misiu
不用谢,目前的解决方案是我决定展示一个Visual Studio错误。我对帖子进行了编辑。 - Reza Aghaei
另一个解决方法是 if (host.RootComponent is Form) defaultValues["Parent"] = host.RootComponent; 它将更改拖放目标为 Form。我更喜欢显示错误消息。 - Reza Aghaei
谢谢您再次查看此内容。我同意显示错误消息比更改目标更好。我会保留这样做。开发人员将看到该错误一次,下次他会记住 :) - Misiu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接