【问题标题】:C# generics usercontrolC# 泛型用户控件
【发布时间】:2009-08-25 16:24:09
【问题描述】:

我想定义如下控件:

public partial class ObjectSelectorControl<T> : UserControl where T : class 

问题是设计者无法解决这个问题。这个问题有解决办法吗?

【问题讨论】:

  • 你试过的时候,你是怎么在xaml上声明类的?
  • VS 2015.1 开始,Windows 窗体设计器显示具有通用基类的类没有任何问题。 See example.

标签: c# generics user-controls


【解决方案1】:

这行得通

public class Control1<T> : UserControl { ... }

public class Control2 : Control1<double> { ... }

public class Control3 : Control2 { ... }

在这里读过:

Generic User Controls?

【讨论】:

  • +1 与我建议的解决方案几乎相同,但描述得更清楚。
  • 确保将 Control3 放在单独的文件中。
  • 我曾经使用过这种解决方法。但现在它没有,不知道为什么,但我发现解决方案是“我们需要更深入”。我又添加了一个级别,它又可以工作了,所以基本上就像“public class Control4 : Control3 { ... }”。
  • “代理”类可以在同一个文件中声明。在这里查看答案:stackoverflow.com/questions/2546699/…
  • VS 2015.1 开始,Windows 窗体设计器显示具有通用基类的类没有任何问题。 See example.
【解决方案2】:

听起来很像我们在项目中所做的。

有一个通用的基类:

public partial class controlItemList<TBaseItem, TBaseItemCollection> : UserControl, IUIDispatcher
    where TBaseItem : new()
    where TBaseItemCollection : IItemCollection<TBaseItem>

然后为每次使用定义一个非通用版本(设计师仍然无法使用):

public class controlMessagesNonGenericParent : controlItemList<MailItem, MailItemCollection>
{
}

...然后我们派生了可以在设计器中使用的控件:

public partial class controlMessages : controlMessagesNonGenericParent
{
...
}

【讨论】:

  • 不过,您似乎正朝着相反的方向前进。你有一个通用的基础,你正在为设计者创建特定的具体实现。听起来他想创建一个通用控件并进行设计。
  • 你是对的,但是直接使用泛型类作为控件是不可能的。这就是我们对它进行子类化的原因,因此它可以在设计器中使用。子类版本修改行为的事实在这里无关紧要。
  • 对,这是不可能的,但似乎并没有解决他的问题。这不是可以让他解决问题的“黑客”。实际上,似乎解决方案朝着另一个方向发展(创建一个不通用的控件,进行设计,然后对其进行子类化并使其通用)更有意义。我看不出这如何解决任何问题。
  • 通用控件可以在设计器中打开!它的实例不能直接放在表单上。
  • 该死的拼写错误,抱歉 ;) 使用我上面发布的代码,controlItemList 和 controlMessages 都可以在设计器中作为控件打开。不过,只有 controlMessages 可以放在工具箱中并使用。
【解决方案3】:

我不知道在什么时候(使用哪个 C#/.NET/VS 版本更新),但现在可以像创建任何其他泛型类一样创建泛型控件。

如果您在 VS 中以标准方式创建 UserControl(即通过 GUI 添加它),您只需在类声明的两个部分(“基”类代码和设计器管理文件)中添加 &lt;T&gt;。实际上,这就是您引用的代码中的内容。

【讨论】:

    【解决方案4】:

    为了能够使用设计器,您的控件可以做什么或不可以做什么有一些限制。从根本上说,它们都围绕着能够实例化你的类的设计器(必须有一个无参数的构造函数,不能是abstract,等等)。因为设计者不知道将什么类型作为通用参数传递(我怀疑这甚至是一个考虑因素),所以您的类不能被实例化。

    您最好的希望是创建您的UserControl 并将构造函数更改为protected(我相信这会起作用,因为设计师使用反射并忽略可见性,但我不是 100% 肯定的)。然后,您可以从 UserControl 继承并创建您的泛型类并调用基 (protected) 构造函数。

    【讨论】:

      【解决方案5】:

      我不相信这是可能的,因为设计器调用了你的类的一个实例。如果使用泛型,设计者不知道将什么类型传递给 'T'。

      【讨论】:

        【解决方案6】:

        https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=105876

        该错误已发布到微软网站,您可以看到它被标记为“推迟”,目前没有解决方案! .

        【讨论】:

        • 看起来并不像“错误”,这是使用泛型的结果。也许他们可以提供未来的增强功能,允许您选择要提供的类型,但我不会将其归类为“错误”。
        【解决方案7】:

        使用组合而不是泛型。不要使用 ObjectSelectorControl,而是提供另一种类型的泛型成员(Selector&lt;T&gt; 可能)并对该对象采取行动,而不是试图强迫自己成为泛型。

        【讨论】:

        • 也许我错了,但是如果您在 UserControl 中使用组合:a)您必须指定泛型属性的类型,或者 b)您必须让您的类也泛型,所以我不明白您的意思意思。
        • 组合不是泛型的替代技术。也许可以设计一个使 WinForms 与泛型一起使用的解决方案,涉及组合,但在这种情况下,您的答案并不表明任何方向。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-12-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多