我有一个特定的要求来创建具有特定常用功能的用户控件。对于该控件,我还要求允许其他开发人员在设计器模式下添加控件以制作特定的 UI。为此,我创建了一个用户控件,添加(示例)标签和按钮。我还添加了一个面板,允许在控件的特定区域添加附加控件。
然后,我通过添加 [Designer] 标记和 [ControlDesigner] 使该类在设计器模式下可见。这给出了添加具有一些固定内容的用户控件以及向页面添加更多控件的预期效果。问题是用户可以在设计模式下移动面板,而 VisualStudio 会感到困惑,创建循环引用..我一定遗漏了什么?即使我需要启用设计模式,我也可以关闭面板的调整大小/定位吗?
注意:我也尝试在设计模式下只使用用户控件,但添加的控件一直在用户控件上的固定控件后面消失。
代码和示例如下.. 欢迎任何建议/修复..
上图是带有面板的用户控件的视觉效果
上面是一个包含用户控件的表单,并在面板上添加了一个自定义按钮。 注意面板拖动是启用的,如果触摸,在 form.designer.cs 文件中创建循环引用,并且项目变得不稳定。
最后是用户控制类
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Diagnostics;
using System.Windows.Forms.Design;
namespace wfcLib
{
[DesignerAttribute(typeof(MyControlDesigner))]
[Designer("System.Windows.Forms.Design.ParentControlDesigner, System.Design", typeof(IDesigner))]
public partial class ucInput : UserControl
{
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public Panel InternalPanel
{
get { return pnlContent; }
set { pnlContent = value; }
}
public ucInput()
{
InitializeComponent();
}
}
[System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")]
public class MyControlDesigner : System.Windows.Forms.Design.ControlDesigner
{
public override void Initialize(IComponent c)
{
base.Initialize(c);
ucInput ctl = (ucInput)c;
EnableDesignMode(ctl.InternalPanel, "InternalPanel");
}
}
}
除了我关于使用具有Panel
覆盖SelectionRules
属性的自己的设计器的派生的评论之外,另一种方法是利用设计器的ISelectionService来检测所选组件中的更改,如果它被选中,则删除面板。
这是通过覆盖控件的Site
属性来设置挂钩来实现的。另请注意,我将InternalPanel
属性更改为只读,因为您确实不希望该属性可写。
[DesignerAttribute(typeof(MyControlDesigner))]
[Designer("System.Windows.Forms.Design.ParentControlDesigner, System.Design", typeof(IDesigner))]
public partial class ucInput : UserControl
{
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public Panel InternalPanel
{
get { return pnlContent; }
}
public ucInput()
{
InitializeComponent();
}
private ISelectionService selectionService;
private IDesignerHost host;
public override ISite Site
{
get
{
return base.Site;
}
set
{
host = null;
UnSubscribeFromSelectionService();
base.Site = value;
if (value != null)
{
host = (IDesignerHost)this.Site.GetService(typeof(IDesignerHost));
if (host != null)
{
if (host.Loading)
{
// defer subscription to selection service until fully loaded
host.Activated += Host_Activated;
}
else
{
SubscribeToSelectionService();
}
}
}
}
}
private void Host_Activated(object sender, EventArgs e)
{
host.Activated -= Host_Activated;
SubscribeToSelectionService();
}
private void SubscribeToSelectionService()
{
selectionService = (ISelectionService)this.Site.GetService(typeof(ISelectionService));
if (selectionService != null)
{
selectionService.SelectionChanging += OnSelectionChanging;
}
}
private void UnSubscribeFromSelectionService()
{
if (selectionService != null)
{
selectionService.SelectionChanging -= OnSelectionChanging;
}
}
private void OnSelectionChanging(object sender, EventArgs e)
{
if (selectionService.GetComponentSelected(pnlContent))
{
selectionService.SelectionChanging -= OnSelectionChanging;
selectionService.SetSelectedComponents(new[] { pnlContent }, SelectionTypes.Remove);
selectionService.SelectionChanging += OnSelectionChanging;
}
}
}
编辑:原始代码忽略SelectionService
了IDesignerHost
在加载时不可用的原因。添加了将订阅推迟到IDesignerHost
激活的代码。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句