Rya*_*ndy 7 .net c# user-controls custom-controls winforms
所以我们有一个C#WinForms项目,其中包含一个包含数百万UserControl的表单.除了自己的特定成员之外,每个都UserControl自然地暴露所有UserControl方法,属性等.
我一直在想减少处理这些问题的复杂性的一种方法UserControl是通过接口访问它们.因此,而不是拖放到UserControl表单上,在构造函数中这样的东西:
public class MyGiantForm
{
ICustomerName cName;
public MyForm()
{
InitializeComponent();
var uc = new SomeCustomerNameUserControl();
this.Controls.Add(uc);
cName = uc;
}
}
Run Code Online (Sandbox Code Playgroud)
SomeCustomerNameUserControl实现ICustomerName,自然地,并ICustomerName包含我真正关心的特定属性(比如说FirstName和LastName).通过这种方式,我可以UserControl通过cName成员参考,而不是被所有UserControl成员击败,我只得到那些成员ICustomerName.
一切都很好,但问题是,如果我这样做,我SomeCustomerNameUserControl在Designer 中看不到.有谁知道我可以做到这一点,但仍然看到UserControl表格的设计表面?
编辑:执行此操作的一种方法是将控件放在基本表单上,这种方法并不过分复杂.默认情况下(在C#中)控件成员是私有的.然后我为每个控件创建一个属性,通过接口公开它.
但是,我会对其他一些方法感兴趣,即使它更复杂.似乎有一些方法可以用IDesignerHost来做,但我找不到任何适用的例子.
如果SomeCustomerNameUserControl定义如下:
class SomeCustomerNameUserControl : UserControl, ICustomerName
{
}
Run Code Online (Sandbox Code Playgroud)
您仍然可以在设计器中删除此控件(创建someCustomerNameUserControl1),并在需要时执行以下操作:
ICustomerName cName = someCustomerNameUserControl1;
Run Code Online (Sandbox Code Playgroud)
也许我错过了什么,但我认为就是这么简单.
有一种方法可以实现你想要的 - 隐藏你不想看到的成员 - 但是让它自动应用,而不需要其他人使用自定义界面进行合作.您可以通过重新引入您不想看到的所有成员并使用属性标记它们来实现.
这就是Windows Forms所做的事情,例如,基类属性对于特定的后代并不意味着什么.例如,Control有一个Text属性,但是TextControl对一个Text属性没有意义.因此,TabControl会覆盖Text属性,并向其覆盖添加属性,说"顺便说一下,不要在Property Grid或Intellisense中显示我的Text属性".该物业仍然存在,但由于你从未见过它,它不会妨碍你.
如果向成员(属性或方法)添加[EditorBrowsable(EditorBrowsableState.Never)]属性,则Intellisense将不再在其代码完成列表中显示该成员.如果我正确理解你的问题,这是你想要实现的重大事情:使应用程序代码难以偶然使用该成员.
对于属性,您可能还希望添加[Browsable(false)]以隐藏属性网格中的属性,以及[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]以防止设计器将属性的值写入.designer.cs文件.
这些将使得意外使用方法/属性变得非常困难.但是,它们仍然不是保证.如果你确实需要保证,那么也要输入[Obsolete]属性,并使用"将警告视为错误"进行构建 - 然后你就会得到照顾.
如果基本成员是虚拟的,您可能想要覆盖它,并让覆盖只是调用base.不要抛出异常,因为在正常的事件过程中,被覆盖的成员可能会被基类调用.另一方面,如果基本成员不是虚拟的,那么你想使用"new"而不是"override",你可以决定你的实现应该调用base,还是只抛出异常 - 没有人应该使用无论如何你重新引入的成员,所以它应该没关系.
public class Widget : UserControl
{
// The Text property is virtual in the base Control class.
// Override and call base.
[EditorBrowsable(EditorBrowsableState.Never)]
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[Obsolete("The Text property does not apply to the Widget class.")]
public override string Text
{
get { return base.Text; }
set { base.Text = value; }
}
// The CanFocus property is non-virtual in the base Control class.
// Reintroduce with new, and throw if anyone dares to call it.
[EditorBrowsable(EditorBrowsableState.Never)]
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[Obsolete("The CanFocus property does not apply to the Widget class.")]
public new bool CanFocus
{
get { throw new NotSupportedException(); }
}
// The Hide method is non-virtual in the base Control class.
// Note that Browsable and DesignerSerializationVisibility are
// not needed for methods, only properties.
[EditorBrowsable(EditorBrowsableState.Never)]
[Obsolete("The Hide method does not apply to the Widget class.")]
public new void Hide()
{
throw new NotSupportedException();
}
}
Run Code Online (Sandbox Code Playgroud)
是的,这是一项相当多的工作,但你只需要做一次......每个成员,每班......嗯,是的.但是,如果这些基层成员真的不适用于你的班级,并且拥有它们会导致混乱,那么可能值得去努力.
使用设计器添加 UserControl 后,可以在“属性”窗口中将“GenerateMember”设置为 false 以禁止生成成员。
然后,您可以在构造函数中使用其他一些技术来分配您的 cName 引用,例如:
foreach(Control control in this.Controls)
{
cName = control as ICustomerName;
if (cName != null) break;
}
Run Code Online (Sandbox Code Playgroud)
cName 将成为对 UserControl 的唯一引用。
| 归档时间: |
|
| 查看次数: |
7560 次 |
| 最近记录: |