Generic base class for WinForm UserControl - c#

I created a generic base class for a WinForm UserControl:
public partial class BaseUserControl<T> : UserControl
{
public virtual void MyMethod<T>()
{
// some base stuff here
}
}
And a UserControl based on that:
public partial class MyControl : BaseUserControl<SomeClass>
{
public override void MyMethod<SomeClass>()
{
// some specific stuff here
base.MyMethod<SomeClass>();
}
}
It works fine, but MyControl cannot be edited in the VisualStudio Designer, because it says it cannot load the base class.
I tried to define another class BaseUserControl, non generic, hoping it would load it, but the trick doesn't seem to work.
I already have a workaround: define an interface, IMyInterface<T>, and then create my control as
public partial class MyControl : UserControl, IMyInterface<SomeClass>
But I lose my base virtual methods (not a big deal, but still...).
Is there a way to create a base generic class for a UserControl, with the possiblity to edit it in the VisualStudio Designer?

We're doing the same thing and we work around by specializing a class first and derive from the specialized class.
Using the code from your example this means something like:
public partial class UserControl : UserControlDesignable
{
...
}
public class UserControlDesignable : BaseUserControl<Someclass> { }
The designer is still acting flaky sometimes - but most of the time it works.

You'll have to trick the designer by adding a 'regular' class that inherits from your generic base form.
Your designable form should then inherit from this class.
The following 2 class definitions are thus in the same file. You'll have to make sure that the class that inherits from the generic base user-control, is the last class in the file.
public MyForm : EditableCustomerForm
{}
public EditableCustomerForm : GenericForm<Customer>
{}
The designer will display the first class in the code file that it encounters.

Well this appears to be a bug in Visual studio.
By digging into the framework (actually by adding a RootDesignerSerializer with a custom type derived from CodeDomSerializer and overriding the serialize method), I was able to prove that the VS Code Dom provider is actually parsing wrong the generic classes, and instead of considering it as a generic class it is considering it as a regular class with the name class<T>, which Type.GetType() can of course not find.
I am still searching for a way to work around it, but in the mean time one can use the solutions above.
There is a Microsoft.Connect bug report on it, please vote on it at https://connect.microsoft.com/VisualStudio/feedback/details/797279/win-forms-designer-error-when-inheriting-from-a-generic-form

Related

C# - How to create constructor for inherited class where parent class only has static constructor

For example, say I wanted to create a class that inherits System.Diagnostics.StopWatch, and for this example pretend that System.Diagnostics.Stopwatch.StartNew() is the only public constructor for that class (I know its not, but I'm trying to inherit a different class where that is the case) :
public class Example : System.Diagnostics.Stopwatch
{
public Example()
{
// ... return System.Diagnostics.Stopwatch.StartNew();
}
}
I know there are obvious workarounds, but just wondering if this is possible in C#
There are basically three scenarios where you can't inherit from a class:
The intended parent class is declared as sealed, which prohibits inheriting from it.
The intended parent class doesn't have an accessible constructor.
The intended parent class is a static class.
If you are in one of these 3 scenarios, you will not be able to inherit from that class, plain and simple, don't look for a usable workaround because there isn't.

Design view of Form class that inherits from BaseForm<T> [duplicate]

I am trying to clean up all designer errors in our solutions and ran into the following error:
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: DoubleAttributeTextBoxBase --- The base class 'NumericAttributeTextBoxBase' could not be loaded. Ensure the assembly has been referenced and that all projects have been built.
The classes are both defined in the same assembly so I know it's not a reference problem. I'm wondering if it has anything to do with the fact that the base class is generic. Any ideas?
public class DoubleAttributeTextBoxBase : NumericAttributeTextBoxBase<double>
public class NumericAttributeTextBoxBase<T> : TextBox where T : IComparable, IComparable<T>
The base class for a class being designed must be non-abstract and non-generic. To make a class that inherits from a generic class designable. The workaround is to insert a trivial non-generic class in-between:
public partial class DoubleAttributeTextBoxBase
: NumericAttributeTextBoxBaseOfDouble
{
public DoubleAttributeTextBoxBase()
{
InitializeComponent();
}
// Now DoubleAttributeTextBoxBase is designable.
}
public class NumericAttributeTextBoxBaseOfDouble
: NumericAttributeTextBoxBase<double>
{
}
To make this as simple as possible, you can even put the non-generic class in the same file as the class you want to design. Just make sure to put it after the class (as I have done above) because the designer expects the first class in the file to be the one being designed.
I don't know of a solution, this has been a severe limitation of Visual studio since C# 2.0 came out. The only thing I can say is to add that control to the page at runtime, then at least you can have your designer back for everything else.
from msdn:
Your component or control cannot be a generic type, which is also called a template type or a parameterized type. The design environment does not support generic types.
http://msdn.microsoft.com/en-us/library/ms171843.aspx

Winforms: best approach to deal with 'unsupported generic base class' in designer [duplicate]

I created a generic base class for a WinForm UserControl:
public partial class BaseUserControl<T> : UserControl
{
public virtual void MyMethod<T>()
{
// some base stuff here
}
}
And a UserControl based on that:
public partial class MyControl : BaseUserControl<SomeClass>
{
public override void MyMethod<SomeClass>()
{
// some specific stuff here
base.MyMethod<SomeClass>();
}
}
It works fine, but MyControl cannot be edited in the VisualStudio Designer, because it says it cannot load the base class.
I tried to define another class BaseUserControl, non generic, hoping it would load it, but the trick doesn't seem to work.
I already have a workaround: define an interface, IMyInterface<T>, and then create my control as
public partial class MyControl : UserControl, IMyInterface<SomeClass>
But I lose my base virtual methods (not a big deal, but still...).
Is there a way to create a base generic class for a UserControl, with the possiblity to edit it in the VisualStudio Designer?
We're doing the same thing and we work around by specializing a class first and derive from the specialized class.
Using the code from your example this means something like:
public partial class UserControl : UserControlDesignable
{
...
}
public class UserControlDesignable : BaseUserControl<Someclass> { }
The designer is still acting flaky sometimes - but most of the time it works.
You'll have to trick the designer by adding a 'regular' class that inherits from your generic base form.
Your designable form should then inherit from this class.
The following 2 class definitions are thus in the same file. You'll have to make sure that the class that inherits from the generic base user-control, is the last class in the file.
public MyForm : EditableCustomerForm
{}
public EditableCustomerForm : GenericForm<Customer>
{}
The designer will display the first class in the code file that it encounters.
Well this appears to be a bug in Visual studio.
By digging into the framework (actually by adding a RootDesignerSerializer with a custom type derived from CodeDomSerializer and overriding the serialize method), I was able to prove that the VS Code Dom provider is actually parsing wrong the generic classes, and instead of considering it as a generic class it is considering it as a regular class with the name class<T>, which Type.GetType() can of course not find.
I am still searching for a way to work around it, but in the mean time one can use the solutions above.
There is a Microsoft.Connect bug report on it, please vote on it at https://connect.microsoft.com/VisualStudio/feedback/details/797279/win-forms-designer-error-when-inheriting-from-a-generic-form

WPF, share methods between two UserControl classes

I have two UserControl classes, RequiredFields and OptionalFields. I wanted to have a base class, Fields, that would inherit from UserControl and contain methods that both RequiredFields and OptionalFields would use. However, when I try to do that, I get the following error:
Partial declarations of 'MyNamespace.OptionalFields' must not specify different base classes
Here are my class definitions:
public partial class OptionalFields : Fields
public partial class RequiredFields : Fields
public abstract class Fields : UserControl
Even if I make Fields a partial class instead of abstract, or if I make it a regular non-abstract non-partial class, I get the same error.
Is what I'm wanting to do possible/reasonable? If not, what is the best way of sharing methods between UserControl instances?
Do you have an OptionalFields.xaml? If so, it is automatically generating OptionalFields.g.cs which contains the C# code that the XAML represents. It contains a class that inherits from UserControl (or whatever the XAML's root element is).
Try changing the root element in the XAML file to Fields.
Do you need to updated the other side of the partial? I.e. is OptionalFields.Designer.cs inheriting from UserControl still?
Edit: sorry being too winforms, I of course mean OptionalFields.xaml

Create a strongly typed view which inherites a class which is concrete

I am having one class called BaseClass which contains some logic applicable to whole web site.
In order to create a strongly typed view we need to inherit the page from System.Web.Mvc.ViewPage generic class. But In our case I have to Inherit the BaseClass from
System.Web.Mvc.ViewPage to apply some common settings, but the BaseClass should be inherited from System.Web.Mvc.ViewPage<> generic version. But I cannot inherit the BaseClass from System.Web.Mvc.ViewPage<> as it will change other class also. So I created one more class of type BaseClass<> inheriting it from System.Web.Mvc.ViewPage<> and copied the whole code of BaseClass in BaseClass<>. But the code in BaseClass is controlled by other team so it will be changed frequently so my BaseClass<> should be in sync with BaseClass. Please help me in eliminating the code duplication or any other approach to make strongly typed View.
Thanks
Ashwani
Ok... it seems like you can't change the use of this BaseClass for your views.
How about duplicating the logic of ViewPage<TModel>? Have a look at the ViewPage`1.cs file that is in the asp.net mvc source code and duplicate that. That would be the easiest way...
E.g.
public class BaseClass : ViewPage
{
//Custom logic for africa here
}
public class BaseClass<TModel> : BaseClass
{
//Copy and paste all the code from ViewPage`1.cs
//It's not much - about 50 lines.
}
HTHs,
Charles
Ps. The link to the source code is for asp.net mvc 2
Ouch...
I am not sure what you are having in your BaseClass. But I think the best option is to create a BaseViewModel (maybe your BaseClass is you BaseViewModel> and then create specific ViewModels (which inherits from BaseViewModel) for each page.
For example your ViewModels should look something like this:
public abstract class BaseViewModel
{
public string SiteTitle {get;set;}
public int SomeProperty{get;set;}
}
public class UserViewModel: BaseViewModel
{
public string UserName{get;set;}
public string Email{get;set;}
}
and you should create strongly typed view like this:
System.Web.Mvc.ViewPage<UserViewModel>
You can take a look at AutoMapper to simplyfy the mapping process from your custom classes to ViewModels.
Cheers
public abstract class MyBaseView<T> : ViewPage<T>
{
//common logic here
}
public class UserView: MyBaseView<MyUserInfo>
{}

Categories