Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / Languages / C# / February 2008

Tip: Looking for answers? Try searching our database.

VS2008 Form designer does not open form with generic types

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Andrus - 09 Feb 2008 20:11 GMT
I created WinForms form containing generic DataGridView on and some other
controls.
Forms designer will not open this form anymore.
Error text is shown below. Application runs this form OK, rebuild all does
not fix.
I tried to change form base class to non-generic class but this does not
help.

I need to add new button to this form.
Manually changing designer generated code is difficult.
Any idea ?

Andrus.

Error  which I got:

Warning 1 The designer could not be shown for this file because none of the
classes within it can be designed.  The designer inspected the following
classes in the file:

BrowseForm --- The base class 'MyApp.ARBusinessBaseForm<T>' could not be
loaded.  Ensure the assembly has been referenced and that all projects have
been built.  0 0

                 at
System.ComponentModel.Design.Serialization.CodeDomDesignerLoader.EnsureDocument(IDesignerSerializationManager
manager)
                 at
System.ComponentModel.Design.Serialization.CodeDomDesignerLoader.PerformLoad(IDesignerSerializationManager
manager)
                 at
Microsoft.VisualStudio.Design.Serialization.CodeDom.VSCodeDomDesignerLoader.PerformLoad(IDesignerSerializationManager
serializationManager)
                 at
Microsoft.VisualStudio.Design.Serialization.CodeDom.VSCodeDomDesignerLoader.DeferredLoadHandler.Microsoft.VisualStudio.TextManager.Interop.IVsTextBufferDataEvents.OnLoadCompleted(Int32
fReload)
Nicholas Paldino [.NET/C# MVP] - 09 Feb 2008 22:11 GMT
Andrus,

   You can't use generic types with the designer.  The designer doesn't
know how to instantiate the instance because it doesn't know what to use for
the type parameters.

   You simply have to change the code by hand, or you have to make it
non-generic.

Signature

         - Nicholas Paldino [.NET/C# MVP]
         - mvp@spam.guard.caspershouse.com

>I created WinForms form containing generic DataGridView on and some other
> controls.
[quoted text clipped - 34 lines]
> Microsoft.VisualStudio.Design.Serialization.CodeDom.VSCodeDomDesignerLoader.DeferredLoadHandler.Microsoft.VisualStudio.TextManager.Interop.IVsTextBufferDataEvents.OnLoadCompleted(Int32
> fReload)
Andrus - 10 Feb 2008 00:24 GMT
How to solve ?

Is it possible and reasonable to use #ifdef to create non-generic version
for designer ?

Or must I remove all generic types manually from code to invoke designer and
put them back after using designer ?

Andrus.

> Andrus,
>
[quoted text clipped - 44 lines]
>> Microsoft.VisualStudio.Design.Serialization.CodeDom.VSCodeDomDesignerLoader.DeferredLoadHandler.Microsoft.VisualStudio.TextManager.Interop.IVsTextBufferDataEvents.OnLoadCompleted(Int32
>> fReload)
Marc Gravell - 10 Feb 2008 10:04 GMT
Well, how much of the form uses generics? One approach could be to
have a standard form/control for the designer, i.e.

public class Foo : Form {...}

And then put all the generic stuff into a subclass:

public class Bar<T> : Foo {... stuff involving T; just a flat code
file...}

For designer stuff you use Foo; for code (and instantiation) you look
mainly at Bar<T> as code.

Since they are *essentially* the same form (so no encapsulation fuss),
I suppose you could make the controls available (protected) either at
the field or property level.

Marc
Marc Gravell - 10 Feb 2008 10:07 GMT
(minor; since Foo and Foo<T> resolve separately, you could name them
such without issue)
Andrus - 10 Feb 2008 11:34 GMT
> Since they are *essentially* the same form (so no encapsulation fuss),
> I suppose you could make the controls available (protected) either at
> the field or property level.

I have deep form hiearchy:

Form
BaseForm<T>
 BusinessForm<T>
    BrowseForm<T>

etc.
and every level need to be designed.
So your solution requires:

1. Add wrapper classes:

Form
BaseForm<T>
  BaseFromWrapper
 BusinessForm<T>
  BusinessFromWrapper
    BrowseForm<T>
       BrowseFormWrapper

2. Change visibility of members  from private to protected only to satisfy
designer.

The other solution wound to remove generic types, pass Type t as parameter
and use reflection inctead of generic. As far as I now passing type
parameter + using reflection can
implement every generic types feature, is it so ?

Which is best way ?

Andrus.
Marc Gravell - 10 Feb 2008 13:38 GMT
> I have deep form hiearchy:

Fair enough; then don't use the approach I mentioned; 'twas only an
idea (and you didn't mention the hierarchy... I tend to avoid overuse
of inheritance in this scenario, as I rarely find it helps - but if it
helps you, great).

> 2. Change visibility of members  from private to protected only to satisfy
> designer.

Actually it was only to make it possible for the generic part of the
class to access the controls; the designer wouldn't be used with the
generic form, so it is nothing to do with the designer.

> As far as I now passing type
> parameter + using reflection can
> implement every generic types feature, is it so ?

Pretty much - just not nearly as convenient nor elegant, and without
compile-time constraint checking.

Marc
Andrus - 10 Feb 2008 18:41 GMT
> Fair enough; then don't use the approach I mentioned; 'twas only an
> idea (and you didn't mention the hierarchy... I tend to avoid overuse
> of inheritance in this scenario, as I rarely find it helps - but if it
> helps you, great).

I can flatten hieararchy if you think  this is better.
Framework which I studied uses 5 level form hiearchy.  So I thought that
this is good design and tried to implement my forms in similar way.

Using your hint I re-looked into my form hiearchy. Some classes contain few
methods so they can be eliminated.
I'm thinking about the following hiearchy:

Form - net base class
   Baseform - contains base routines for every form used in application:
                          form position save-restore etc.
        BusinessForm<T> ( contains Grid<T> )
                - contains common logic and controls for single linear
entity type
                (Customer, Product etc). editing.
            BrowseForm<T>  - contains few additional buttons specific for
some entities.

Is this best design or should I simplify it more ?

Andrus.
Andrus - 10 Feb 2008 14:27 GMT
> Well, how much of the form uses generics?

Form type parameter  parameter is DLinq entity type T
Form contains generic grid with same type parameter T:

partial class BrowseForm<T> {
...
private MyApp.Grid<T> grid;
}

> One approach could be to
> have a standard form/control for the designer, i.e.
[quoted text clipped - 5 lines]
> public class Bar<T> : Foo {... stuff involving T; just a flat code
> file...}

This allows to wrap BrowseForm<T> only.
How to create non-generic version of Grid<T> member ?

Andrus.
Nicholas Paldino [.NET/C# MVP] - 10 Feb 2008 15:18 GMT
You might want to consider making all of your types non-Generic, and
adding a method that is called which you can set the type that the form uses
for browsing and whatnot, something like:

SetBrowseType(Type type)

   And have a generic overload on the method as well:

SetBrowseType<T>()

   It seems you are using the type parameter to convey type information,
which is poor design if you don't have a non-generic alternative.

   I would have recommended passing the type in the constructor, but that
would have broken designer support as well =)

   Depending on how much actual functionality you expose through generics,
this might be a simpler solution for you.

Signature

         - Nicholas Paldino [.NET/C# MVP]
         - mvp@spam.guard.caspershouse.com

>> Well, how much of the form uses generics?
>
[quoted text clipped - 20 lines]
>
> Andrus.
Andrus - 10 Feb 2008 19:10 GMT
Nicholas,

>    You might want to consider making all of your types non-Generic, and
> adding a method that is called which you can set the type that the form
> uses for browsing and whatnot, something like:
>
> SetBrowseType(Type type)

My planned hiearchy looks like:

Form - net base class
   Baseform - contains base routines for every form used in application:
                          form position save-restore etc.
        BusinessForm<T> ( contains Grid<T> )
                - contains common logic and controls for single linear
entity type
                (Customer, Product etc). editing.
            BrowseForm<T>  - contains few additional buttons specific for
some entities.

So if I understand your recommendation properly, I must change type T to
Form and Grid constructor parameter. I see no reason to use SetBrowseType()
since type can be passed in constructor. Why SetBrowseType() is better than
using BrowseForm(Type t) constuctor ?

>    And have a generic overload on the method as well:
>
> SetBrowseType<T>()

Why this is better than using Marc hint to create generic wrapper for
designer class:

class BrowseForm<TEntity>: BrowseForm  {
  public BrowseForm<TEntity>( .... ): base(typeof(TEntity), ..... ) { ...}
}

BrowseForm<TEntity> makes few usagw of type T, most usage is in grid.
So I think I must use only non-generic BrowseForm and drop generic classes
at all?

>    It seems you are using the type parameter to convey type information,
> which is poor design if you don't have a non-generic alternative.

T is linear entity type (Customer, Produce, Emplyee etc) which is edited in
form in Grid.
Is it poor design only since it is not supported by Designer ?
Will creating non-generic intermediate class only to satisfy designer make
it good design ?

>    I would have recommended passing the type in the constructor, but that
> would have broken designer support as well =)

Is it reasonable to create parameterless constructor only for designer
support :

class BrowseForm {
   // Real constructor
  public BrowseForm(Type entityToEdit, ..... ) { ...}

  // Empty constructor for designer support, prevent its use in code.
  public BrowseForm() { Debug.Assert(false); }
}

In this case SetBrowseType() method is not required and designer can open
form.

Unresolved issue is using Grid<T> in designer.

As I understand only way is to change this grid to non generic Grid( Type
t ) and add parameterless constructor to Grid to satisfy designer.
In this case I lose compile time checking of type parameter constraints and
must use heavy
reflection in Grid class.
Is this best solution to create generic entity editing grid whose containg
form can be designed in designer?

Or should I stop using designer and design forms manually to keep code clean
?

Andrus.
Marc Gravell - 10 Feb 2008 21:02 GMT
> Unresolved issue is using Grid<T> in designer.
> ...
> Or should I stop using designer and design forms manually to keep code clean ?

Maybe use the designer for general layout, but leave a Panel as a
placeholder for you grid; have an Initialise<T>() method with whatever
arguments and constraints you need, and just setup the grid in this
generic method - i.e.

Initialise<T>() {
 Grid<T> grid = new Grid<T>();
 grid.Dock = {blah}.Fill;
 gridPanel.Controls.Add(grid);
 // etc
}

Marc
Nicholas Paldino [.NET/C# MVP] - 11 Feb 2008 17:24 GMT
Andrus,

   See inline:

> My planned hiearchy looks like:
>
[quoted text clipped - 12 lines]
> SetBrowseType() since type can be passed in constructor. Why
> SetBrowseType() is better than using BrowseForm(Type t) constuctor ?

   As I mentioned, you will not have designer support if you don't have a
default constructor.  Since that is the aim here, having a constructor which
takes the Type is a little bit of a waste, since you will have to add a
method which will take the Type anyways (having the default constructor
^just^ for designer support is a bad idea).

>>    And have a generic overload on the method as well:
>>
[quoted text clipped - 10 lines]
> So I think I must use only non-generic BrowseForm and drop generic classes
> at all?

   That could work, but it depends on how much the Grid<T> and the
BrowseForm<T> are related.  If the Grid expects to access elements on the
parent for some reason, then you are adding this extra constraint that there
be this wrapper class associated with your form which could cause some more
headaches.

>>    It seems you are using the type parameter to convey type information,
>> which is poor design if you don't have a non-generic alternative.
[quoted text clipped - 4 lines]
> Will creating non-generic intermediate class only to satisfy designer make
> it good design ?

   I say it is poor design because it appears that the only reason you are
passing T is to get type information from T.  I don't know if the type T has
any constraints on it, so I don't know if you are doing anything with T
other than reflecting on it to get specific type information (if you have
constraints, you aren't reflecting most likely, but you aren't indicating
that you do have constraints).

   Having ^just^ a generic method where the type parameter is used ^solely^
for the purpose of conveying type information is bad design.  You would want
an additional method which would pass an instance of Type to convey the type
information, because the code that calls your code might not always have
type information at compile time.

>>    I would have recommended passing the type in the constructor, but that
>> would have broken designer support as well =)
[quoted text clipped - 12 lines]
> In this case SetBrowseType() method is not required and designer can open
> form.

   I would say no, because then you are polluting your design and with the
possibility that someone could call the parameterless constructor, you put
them in a situation where the form is unusable because they can't set the
type information that they would call in the constructor.

> Unresolved issue is using Grid<T> in designer.
>
[quoted text clipped - 5 lines]
> Is this best solution to create generic entity editing grid whose containg
> form can be designed in designer?

   The same issues with the Grid<T> are the ones you are facing here,
really.  You need a way to convey the type information on the parent to the
Grid and make it non generic (if you want designer support).

> Or should I stop using designer and design forms manually to keep code
> clean ?

   Well, that depends on what your pain threshold is.  If it's a simple
form, then maybe it will work, but if it is something more complex (which I
imagine it is), then you probably are going to hurt yourself a great deal by
eliminating designer support.

Signature

         - Nicholas Paldino [.NET/C# MVP]
         - mvp@spam.guard.caspershouse.com

> Andrus.

Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.