C# 抽象类中定义的非抽象事件赢得';派生类的设计器中不显示
我使用下面列出的类来创建一个UserControl,它包装一个ComboBox,当内部ComboBox的选择被更改时,它可以接受一个列表并返回一个类型为T的对象 代码中的一切都很好,正如我所期望的那样,但在使用控件时,我无法让SelectedItemChanged事件在设计器中显示。当抽象基类是非抽象的时候,它工作得很好,但是我试图将5个基本上重复的控件压缩成一个 不重要的部分被剪掉了C# 抽象类中定义的非抽象事件赢得';派生类的设计器中不显示,c#,winforms,generics,user-controls,abstract,C#,Winforms,Generics,User Controls,Abstract,我使用下面列出的类来创建一个UserControl,它包装一个ComboBox,当内部ComboBox的选择被更改时,它可以接受一个列表并返回一个类型为T的对象 代码中的一切都很好,正如我所期望的那样,但在使用控件时,我无法让SelectedItemChanged事件在设计器中显示。当抽象基类是非抽象的时候,它工作得很好,但是我试图将5个基本上重复的控件压缩成一个 不重要的部分被剪掉了 using System; using System.Collections.Generic; using S
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Forms;
namespace UserComboTest
{
public abstract partial class DropDownList<T> : UserControl where T : class
{
protected abstract int FindIndex(T item);
public abstract void Populate(List<T> items, T defaultItem);
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible), Browsable(true)]
public event EventHandler<SelectedItemEventArgs> SelectedItemChanged;
private void comboBox_SelectedIndexChanged(object sender, EventArgs e)
{
if (null != SelectedItemChanged)
{
SelectedItemChanged(this, new SelectedItemEventArgs(Selected));
}
}
public class SelectedItemEventArgs : EventArgs
{
public SelectedItemEventArgs(T selectedItem)
{
Selected = selectedItem;
}
public T Selected { get; private set; }
}
}
public class UserDropDownList : DropDownList<User>
{
protected override int FindIndex(User user)
{
// find index for item
}
public override void Populate(List<User> users, User defaultUser)
{
// populate the list
}
}
}
使用系统;
使用System.Collections.Generic;
使用系统组件模型;
使用System.Windows.Forms;
名称空间用户组合测试
{
公共抽象部分类DropDownList:UserControl其中T:class
{
受保护的抽象int FindIndex(T项);
公共摘要无效填充(列表项,T默认项);
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible),可浏览(true)]
公共事件处理程序SelectedItemChanged;
private void组合框\u SelectedIndexChanged(对象发送方,事件参数e)
{
如果(null!=SelectedItemChanged)
{
SelectedItemChanged(此,新SelectedItemEventArgs(已选));
}
}
公共类SelectedItemEventArgs:EventArgs
{
public SelectedItemEventArgs(T selectedItem)
{
Selected=selectedItem;
}
公共T选择{get;私有集;}
}
}
公共类UserDropDownList:DropDownList
{
受保护的覆盖int FindIndex(用户)
{
//查找项目的索引
}
公共覆盖无效填充(列表用户、用户默认用户)
{
//填充列表
}
}
}
编辑:修复了代码中断问题。我的名称空间和表单都被命名为UserComboTest,因此当它序列化完全限定的类型名(UserComboTest.UserDropDownList)时,它假设它是表单下的成员或类,而不是名称空间。换句话说,它认为它在寻找UserComboTest.UserComboTest.UserDropDownList,但它并不存在。将表单重命名为UserComboTest.UserComboTestForm解决了这一半的问题
还有一个事实是,设计器没有显示SelectedItemChanged事件,如果我手动设置它,它会被删除,因此我必须在InitializeComponent之外设置它,或者找出如何将其序列化。通常,winforms设计器对抽象基类的反应很差。您应该将抽象方法转换为空的虚拟方法,并使类非抽象。刷新以查看您的答案。我把我的删除了。您可能希望提到使用受保护的构造函数或内部构造函数来限制基类的使用,如果这样做的目的是这样的话。另外,在空的virtuals中抛出NotImplementedException或NotSupportedException。我曾经考虑过这一点,因为设计师之前给了我一个没有参数的公共构造函数的口吻。不幸的是,在使类非抽象的同时使这两个方法成为虚拟的仍然不能让事件显示在设计器中,并且我丢失了确保函数实现的编译时检查。