UserControl with generic control - broken in designer - c#

I have a WinForm-UserControl with a generic type for a control. To create the instance, I changed the Designer code:
public class TimeBarForm<T> : where T : TimeBarPanel
{
protected void InitializeComponent()
{
// ...
this.m_timeBarPanel = (T)Activator.CreateInstance(typeof(T));
// ...
}
}
This works fine at compile time but on design time it's broken. On the TimeBarForm:
Failed to parse method 'InitializeComponent'. The parser reported the following error
'Type parameters are not suppported Parameter name: typeSymbol'.
Please look in the Task List for potential errors.
The derived classes just show the default designer for an empty user control.
I also tried to pass the type in the constructor but VS complains that I should not touch autogenerated code (It dosn't like the if-conditions). I want a generic UserControl where I can decide about the specialization of an abstract class/control in a derived type and I should still be able to use the designer in the base class. I'm open to other suggestions to solve this as this might not be the best solution. I'm not very used to UserControl-design.
VS 2015/ .Net 4.6

I've done a somewhat dirty workaround but I can use the designer for the base and derived classes. I removed the generic and replaced the Activator-class with a call to the constructor. When I'm done with designing the base class I coment this line. The derived classes call the constructor to pass the instance:
public TimeBarForm(TimeBarPanel timeBarPanel)
{
this.m_timeBarPanel = timeBarPanel;
InitializeComponent();
}
To make the designer for the derived classes happy, a second constructor provides a default instance:
public TimeBarForm()
{
this.m_timeBarPanel = new TimeBarPanel();
InitializeComponent();
}
Not pretty but I can live with it.

Related

Generic User Control designer error: a new guard page for the stack cannot be created

I have a Generic UserControl as blow:
public partial class TreeNodeView<C,T>: UserControl
{
public TreeNodeView(C foo, T foo1)
{
InitializeComponent();
}
}
Either change the partial class as below:
partial class TreeNodeView<C, T>
And because get this error in partial designer class:
Using the generic type 'TreeNodeView' requires 2 type arguments
in line :
System.ComponentModel.ComponentResourceManager resources =
new System.ComponentModel.ComponentResourceManager(typeof(TreeNodeView));
change it to:
System.ComponentModel.ComponentResourceManager resources = new
System.ComponentModel.ComponentResourceManager(typeof(TreeNodeView<C,T>));
The code compile successful but when want to see the designer i see ma messagebox:
a new guard page for the stack cannot be created
and when press OK visual studio close immediately. Anybody know whats my wrong?
You can't design a control which is a generic type. This is not supported by the WinForms Designer.
Either change your control to a non-generic type and use generic methods instead, or try to design a derived type of which is not generic anymore.

TypeLoadException when Navigating to a page that inherits Page

I'm getting a TypeLoadException when I try to navigate to a custom Page.
This is the base class:
public abstract partial class MyBasePage : Page
{
// Some abstract methods and some View-level stuff
}
And the other class:
public sealed class MyCustomPage : MyBasePage
{
public MyCustomPage() : base()
{
// Some stuff
}
// Methods implementations
}
Note: I also tried removing the abstract modifier (I replaced my abstract prototypes with virtual methods that simply throw a NotImplementedException, so I get the same result in my derived class), but I still get the same exact TypeLoadException.
This is the message I get:
"Could not find Windows Runtime type 'Windows.Foundation'."
And this is the StackTrace
at System.StubHelpers.WinRTTypeNameConverter.GetTypeFromWinRTTypeName(String typeName, Boolean& isPrimitive)
at System.StubHelpers.SystemTypeMarshaler.ConvertToManaged(TypeNameNative* pNativeType, Type& managedType)
at Windows.UI.Xaml.Controls.Frame.Navigate(Type sourcePageType, Object parameter)
[...]
Am I missing anything? I think I probabily messed something up when I inherited the Page class, but I can't find the error and the compiler doesn't show any warnings whatsoever.
Thanks for your help!
Sergio
Update: So it looks like that in Windows Store apps the XAML isn't compiled and the UI is generated at runtime (by parsing the XAML I guess), so it's not actually possible to inherit the XAML.
Is it impossible to do something like that, and do I have to either copy/paste the same XAML in two different pages or to create a single page with different methods depending on the context, or is there another way to "share" the same UI across different pages?
What I need is to get the same exact UI, but with two different classes (I need different types for my navigation method).

How to add a custom control to the toolbox?

I've created a custom control, based on the Picturebox:
public class Timebar : System.Windows.Forms.PictureBox
This works correctly if I create the control manually/set all values etc. etc, at the Form's initialization method.
Now I also found this, at the top of the Toolbox: http://i.imgur.com/4KUc0.png
When I try to insert it via msvc, I get an error however.
Failed to create component 'Timebar'. The error message follows:
'System.MissingMethodException: Constructor on type 'SC.Timebar' not found.
This isn't exactly a huge problem with my component Timebar (as I will add that component manually), but it is with the custom Button class I want to make (something more fancy then the default).
There IS a constructor in the class:
public Timebar(Data refr)
{
this._refr = refr;
}
How can I fix the above error?
Thanks,
~ Tgys
Controls used in the designer must have a parameterless constructor. The designer needs to create one of your controls to display and allow you to manipulate it, but it has no clue as to how it should call a constructor that requires parameters.
So, what I would do is create a parameterless constructor which chains the other constructor using a default value, i.e.,
class Foo
{
public Foo() : this(SomeType.Value) { }
public Foo(SomeType whatever) : { /* do stuff /* }
}

Fix embedded resources for a generic UserControl

During a refactoring, I added a generic type parameter to MyControl, a class derived from UserControl. So my class is now MyControl<T>.
Now I get an error at runtime stating that the embedded resource file MyControl`1.resources cannot be found. A quick look with .NET Reflector shows that the resource file is actually called MyControl.resources, without the `1.
At the start of the MyControl<T>.InitializeComponent method there is this line which is probably the one causing problems:
System.ComponentModel.ComponentResourceManager resources =
new System.ComponentModel.ComponentResourceManager(
typeof(MyControl<>));
How do I force the ComponentResourceManager to use the embedded resource file MyControl.resources? Other ways to resolve this issue are also welcome.
Turns out you can override the resource filename to load by inheriting from ComponentResourceManager like this:
using System;
using System.ComponentModel;
internal class CustomComponentResourceManager : ComponentResourceManager
{
public CustomComponentResourceManager(Type type, string resourceName)
: base(type)
{
this.BaseNameField = resourceName;
}
}
Now I can make sure that the resource manager loads MyControl.resources like this:
System.ComponentModel.ComponentResourceManager resources =
new CustomComponentResourceManager(typeof(MyControl<>), "MyControl");
This seems to work.
edit: the above line is overwritten if you use the designer, because it is in the
generated code region. I avoid the designer and make use of version control tools to revert any unwanted changes, but the solution is not ideal.
In addition to Wim's technique, you can also declare a non-generic base control that has the same name as your generic class, and have your generic control/form derive from that non-generic base class.
This way you can trick both the designer and the compiler into using the resource file from your generic class, and you get permanent designer support once the base class is setup without having to fiddle in the .designer file everytime you rebuild :
// Empty stub class, must be in a different file (added as a new class, not UserControl
// or Form template)
public class MyControl : UserControl
{
}
// Generic class
public class MyControl<T> : MyControl
{
// ...
}
The only requirements are to have exactly the same name for your generic class and its base class, and that the base class must be in another class file, otherwise the designer complains about not finding one of the two classes.
PS. I tested this with forms, but it should work the same with controls.
On my Visual Studio 2008 I have this error:
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MyControl));
Using the generic type 'WindowsFormsApplication1.UserControl1' requires '1' type arguments.
Notice that in my case code was generated without parentheses, <>, after the class name.
It is becoming interesting, see ImageList autogenerates non-compiling code in a Generic User Control.
What they said:
Posted by Microsoft on 7/6/2005 at 2:49 PM
This is an interesting bug. You've hit upon a generic scneario that we do not support in the Windows Forms designer. We will not be able to add support for this in the Whidbey (my note: Visual Studio 2008?) release. We will consider this for a future version. As a workaround, you can use the designer to create a none generic UserControl with a public Type property and then create a generic class that inherits from it and passes T into the base classes Type property.
I suppose this control cannot be designed in the Visual Studio forms designer either.
The simplest and easiest workaround is to make a dummy class for the autogenerated typeof(). You do not need to inherit from it or even expose it to the outside:
// Non-generic name so that autogenerated resource loading code is happy
internal sealed class GridEditorForm
{
}
(In my experience, the time required getting the designer to work around generics was not worth the ideal coolness generics can provide. I won't be using generic windows forms or controls again.)

Extending a class, compiler complains Microsoft.MapPoint.PlugIns.PlugIn does not contain a

I'm following the tutorial's that come with the SDK for Microsoft Virtual Earth, and when I try to create a plugin like it says, the compiler won't let me.
I'm extending the class Microsoft.MapPoint.PlugIn.PlugIn and it has two abstract methods (that the tutorial doesn't talk about) which I have implemented. However, when I compile it, Visual Studio says
'Microsoft.MapPoint.PlugIns.PlugIn' does not contain a constructor that takes '0' arguments
How can I fix this?
You probably need to add a constructor that passes something to the base constructor; add:
class Foo : PlugIn {
public Foo() : base( //****** here
}
when you type base(, intellisense should tell you what you need to give the base-constructor.
edit from searching, you need:
public Foo (Host host)
: base(host)
{
}
If you have a constructor, you need to ensure that the a base class constructor that exists is being called. By default, I believe the compiler attempts to align constructors one for one, but if that's not the functionality you want or that constructor doesn't exist, you need to define the base class constructor to call.
public Class()
: base(/*variables here*/)
{
}

Categories