通用表单和VS设计器

4

我有一个基类

internal partial class View<T> : UserControl
  where T : class
{
    protected T t;
}

我想从View派生出一个子类

internal partial class ViewChild<T> : View<T>
  where T : class
{
}

功能正常,但我无法在VS设计器中编辑ViewChild。我知道问题出在通用基类上。但是我不知道如何在这种情况下避免这个问题。 有没有什么方法可以解决这个问题?

2个回答

3

还有另一种方法,它不依赖于编译器标志:

http://wonkitect.wordpress.com/2008/06/20/using-visual-studio-whidbey-to-design-abstract-forms/

我不建议使用条件编译。最好与框架一起工作,而不是反对它。
基本上,您可以通过现有框架为VS提供不同的类。您可以使用TypeDescriptionProvider属性装饰您的基类,告诉VS使用不同的类作为设计师。
正如原始博客文章中提到的那样,这种解决方法可能存在一些注意事项,但在一个从共同基类继承了25个用户控件的项目中,我已经成功地将其整理好了。

1
这是一个不错的解决方案,但它没有提到泛型。你使用它时是否涵盖了泛型? - Adam Houldsworth
问题域实际上是相同的,即VS托管设计类型的实例。 VS抱怨泛型的原因是它无法实例化它们,就像抽象类一样。在这方面,所有泛型都是伪抽象的;如果没有它们的类型参数,对运行时来说是没有意义的。回答你的问题,我曾经简要使用泛型基类来实现强类型视图(在Winforms中),但是现在我已经放弃了那个特定的架构分支,转而实现真正的功能。我可能会在月底返回它。 - Mel Padden
如果这个周末有时间,我会尝试使用它更新我的旧代码,看看它是否让我设计基类 - 很好的发现。+1 - Adam Houldsworth
我无法使两个抽象类正常工作 :-( 你有没有任何带有解决方案演示的代码链接? - Adam Houldsworth
我要说,我发现当要求VS2010执行这些任务时,它有点不稳定,行为也不可预测。在实施这个过程中,我不得不重新启动它几次。安装一些扩展程序确实有所帮助。总的来说,实际上,我觉得VS中的扩展程序很麻烦,也是不必要的,所以这并不是什么大问题。另一个需要注意的是,如果继承第三方用户控件(我指的是ComponentOne for WinForms),性能会变得棘手。不过,最终还是让它正常工作了,这意味着我不需要在各个地方使用#if块。 - Mel Padden
我会尝试在这个周末回来并发布一些可工作的代码...现在我离开了我使用的机器。 - Mel Padden

2
泛型会破坏设计器,因为它无法在没有类型T的情况下实例化类。我在我的博客文章中解释了一种解决方法:http://adamhouldsworth.blogspot.co.uk/2010/02/winforms-visual-inheritance-limitations.html
简而言之,您需要使用中间类“解析”类型:
- BaseControl<T> : UserControl - CustomerControl_Design : BaseControl<Customer> - CustomerControl : CustomerControl_Design
然后,可以根据DEBUG或RELEASE编译器开关有条件地从代码中切换此类。
#if DEBUG

namespace MyNamespace
{
    using System;


    public partial class CustomerEditorControl_Design : BaseEditorControl<Customer>
    {
        public CustomerEditorControl_Design()
            : base()
        {
            InitializeComponent();
        }
    }
}

#endif

    public partial class CustomerEditorControl
#if DEBUG
        : CustomerEditorControl_Design
#else
        : BaseEditorControl<Customer>
#endif
    {
    }

这将允许您打开CustomerControl的派生类,不幸的是,您将永远无法设计带有泛型签名的UI控件。我的解决方案仅能实现派生项的设计。

我不知道为什么在CustomerControl : BaseControl<Customer>的情况下不起作用,因为类型T已定义,但它简单地不起作用 - 我猜测是由于泛型使用规则。

值得一提的是,微软表示不支持此功能。


据我理解,这只适用于具体的客户类型,如果我想使用不同类型的ViewChild,则无法正常工作。当我将一些基础代码放入View<T>中时,当我使用View<ConcreteType1>、ViewChild<ConcreteType2>、ViewChild<ConcreteType3>等来扩展ViewChild<T>时,它会添加一些额外的代码。 - wince
@wince 你说得对。正如我在答案中所述,它只解决了派生表单的问题。如果您有一个实际上具有内容的通用基本表单,我建议放弃这个想法,并在 shell 表单中执行类似组合的操作。在我的使用中,基本控件仅提供逻辑,而不是视觉效果。 - Adam Houldsworth
@wince 您的 View<T>ViewChild<T> 是否也具有任何可视元素,还是仅仅是代码? - Adam Houldsworth
View<T> 只有代码部分,ViewChild<T> 是一个向导表单,带有一些按钮(返回、下一步、取消),我需要许多不同 T(演示者)的 ViewChild 对象。 - wince
我找到了解决方案。虽然不是很好,但它能够工作。对于设计时间,我只需使用内部类ViewChild<T>:UserControl。 - wince

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接