【问题标题】:UserControl with header and content - Allow dropping controls in content panel and Prevent dropping controls in header at design time带有标题和内容的用户控件 - 允许在内容面板中放置控件并防止在设计时在标题中放置控件
【发布时间】:2018-06-08 10:54:41
【问题描述】:

我写了用户控制(耶!)。但我希望它表现得像一个容器。可是等等!我知道

[Designer("System.Windows.Forms.Design.ParentControlDesigner, System.Design", 
    typeof(IDesigner))]

诡计。

问题是 - 我不希望我的所有控件都像容器一样,而只是其中一部分。一个事实上的面板;)

为了提供更广泛的上下文:我编写了一个具有网格、一些常用按钮、标签和功能的控件。但它也有一部分用户应该放弃他的自定义按钮/控件。只在这个特定的部分控制,别无他处。

有人知道吗?

【问题讨论】:

  • 我不熟悉用户控件,但您不能在您希望用户能够放置控件的区域上放置一个面板吗?也许您还需要更改该面板的modifierproperty
  • @GuidoG - 不幸的是,没有 :(。修饰符在继承时可以正常工作,但据我尝试,没有办法通过这种方式在用户控件上对组件进行“可编辑”。
  • 这可能也是我从不使用用户控件而是直接从我需要的东西或面板继承的原因

标签: c# .net winforms user-controls windows-forms-designer


【解决方案1】:

您应该执行以下操作:

  • 对于您的用户控件,您需要创建一个新的设计器,通过调用EnableDesignMode 方法在设计时启用内部面板。
  • 对于内部面板,您需要创建一个设计器,该设计器禁用移动、调整大小并从设计器中删除某些属性。
  • 您应该注册设计师。

示例

您可以阅读有关此主题的博客文章 here 并克隆或下载一个工作示例:

代码

这里是解决方案不同元素的代码。

您的用户控制

[Designer(typeof(MyUserControlDesigner))]
public partial class MyUserControl : UserControl
{
    public MyUserControl()
    {
        InitializeComponent();
        TypeDescriptor.AddAttributes(this.panel1,
            new DesignerAttribute(typeof(MyPanelDesigner)));
    }
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    public Panel ContentsPanel
    {
        get { return panel1; }
    }
}

内面板设计器

public class MyPanelDesigner : ParentControlDesigner
{
    public override SelectionRules SelectionRules
    {
        get
        {
            SelectionRules selectionRules = base.SelectionRules;
            selectionRules &= ~SelectionRules.AllSizeable;
            return selectionRules;
        }
    }
    protected override void PostFilterAttributes(IDictionary attributes)
    {
        base.PostFilterAttributes(attributes);
        attributes[typeof(DockingAttribute)] = 
            new DockingAttribute(DockingBehavior.Never);
    }
    protected override void PostFilterProperties(IDictionary properties)
    {
        base.PostFilterProperties(properties);
        var propertiesToRemove = new string[] {
            "Dock", "Anchor", "Size", "Location", "Width", "Height",
            "MinimumSize", "MaximumSize", "AutoSize", "AutoSizeMode",
            "Visible", "Enabled",
        };
        foreach (var item in propertiesToRemove)
        {
            if (properties.Contains(item))
                properties[item] = TypeDescriptor.CreateProperty(this.Component.GetType(),
                    (PropertyDescriptor)properties[item],
                    new BrowsableAttribute(false));
        }
    }
}

用户控件设计器

public class MyUserControlDesigner : ParentControlDesigner
{
    public override void Initialize(IComponent component)
    {
        base.Initialize(component);
        var contentsPanel = ((MyUserControl)this.Control).ContentsPanel;
        this.EnableDesignMode(contentsPanel, "ContentsPanel");
    }
    public override bool CanParent(Control control)
    {
        return false;
    }
    protected override void OnDragOver(DragEventArgs de)
    {
        de.Effect = DragDropEffects.None;
    }
    protected override IComponent[] CreateToolCore(ToolboxItem tool, int x,
        int y, int width, int height, bool hasLocation, bool hasSize)
    {
        return null;
    }
}

【讨论】:

  • Reza,当我第一次发现你的帖子时,我希望这对我有用。试图将此示例应用于 TableLayoutPanel。当我将内容面板的类型从 Panel 更改为 TableLayoutPanel (TLP) 并进行测试时,当我将用户控件拖到设计图面上时,我失去了布局面板的设计时功能。例如,当我选择 ContentsPanel 控件时,我看到了 Columns 属性,但是当我将其从 0 更改为 2 时,列不会出现在控件的设计器实例上。我似乎也无法访问更高级的 TLP 属性(例如行/列指标)。
  • @Jazimov 我认为它不适用于TableLayouPanel,因为some limitationsTableLayoutPanel
  • 啊,这就是生活。 :) 对于stackoverflow.com/questions/59965679/… 的问题,我仍然对您的解决方案 2 感到满意。我希望其他人可以从这种方法中受益。
猜你喜欢
  • 2020-04-21
  • 2012-08-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多