I would like to create a partial class for my form. I have a lot of events, and it gets messy, so I would like to break up sections into their own files.
The problem: When I create a partial class of my form, say:
Partial Public Class Form1
End Class
Visual Studio decides I need another form for this partial class.
Questions:
1. How do I create a partial class for a form?
2. If I cant do that, how can I break up all the events in my form into different files?
Yeah, it does. As soon as you drop a control on this phantom form, you'll get the design-time code (InitializeComponent) generated into that source code file. This is compatibility behavior for .NET 1.x, it didn't support the Partial keyword. Which will break the build, there are now two of them. It is somewhat avoidable with careful clicking, but you know it's going to happen sooner or later.
Other things go wrong too btw, the designer can no longer track an event handler when you move it from one file to another. And will readily let you add another, a much trickier source of bugs.
This just doesn't work very well, abandon hope of relying on it to solve your problem.
The generic diagnostic is that a convoluted user interface begets convoluted code. But that ship has sailed, no doubt. A more structural solution is pursuing the MVC model, separating the data from the view of the data. You'll still have a lot of event handlers but they won't do anything more than calling a method of a class that does the real work. Whose source code can of course live in another source code file. The typical hangup is that Windows Forms has no support whatsoever built in for this, you have to craft it by hand. Nothing similar to the MVVM model in WPF.
Something that can work well is isolating control + code into a separate UserControl. You have to do so carefully though, you don't want to have to add a bunch of properties and events that expose internal controls.
Sometimes I create partial classes for better readibility, especially when I have very large classes.
But when I click on the partial class, then the VS IDE will open the form editor showing me an empty form. If I do not care, than I could damage the main form (it seems to be a bug of VS 2008/2010)
A possibility could be using DesignerCategoryAttribute Class
Mark the partial class with the attribute "code".
<System.ComponentModel.DesignerCategory("code")>
Partial Class Form1
End Class
In this way when you click on the file, you open the class in the code editor.
Of course this will apply to all files, also to the main form file.
If you want to edit again your form in the form editor, you have to quote the attribute:
'<System.ComponentModel.DesignerCategory("code")>
Some more details here.
While it does not answer the original question, I found using regions made my code a little more manageable/readable.
#Region "RegionA"
#End Region
I orginally called this method a "hack", thus the comment below.
Not sure what you mean be "Visual Studio decides you need another form", however, are you sure the new Form1 partial class is declared in the corresponding original namespace?
All partial classes for a given .NET type must be declared in the same namespace of course (whatever files they're stored on).
I appreciate the answers given by Hans and I'm not disputing these at all. It is curious though that in Visual Studio 2010, when you create a form called say Main you get a Main.designer.vb which is a partial class. It says 'Partial Class Main' at the top. This class doesn't open a form when clicked. It also includes reference to Event Handlers. So I was wondering how do they get around this? Is there a way to create one of these 'special' partial classes that work as we would expect.
I noticed that when I created a Form Partial class, that the icon went from a class icon to a form icon. The icon associated with the Main.designer.vb file looks like a class icon with a arrow.
what worked for me (VS 2010) was naming Form1 class, already saved in Form1.vb with its own designer (Form1.Designer.vb) as:
Public Class Main 'saved in Form1.vb
VS updated the name in the designer as:
Partial Class Main 'saved in Form1.Designer.vb
then I created another "partial class" with the same name:
Partial Class Main 'saved in Main.vb
Whether I am editing Form1.vb or Main.vb VS shows me on the top navigation pan all the routines, functions, subs, even background workers and timers. For event handlers, to avoid the loophole mentioned earlier (you click on a control in the layout designer and a brand new event handler will be created in the original Form1.vb) I go:
Partial Public Class Main 'in Form1.vb file
Private Sub SomeControl_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles SomeControl.Click
Call SomeControlClick(sender, e)
End Sub
End Class
Partial Public Class Main 'then in Main.vb file
Private Sub SomeControlClick(ByVal sender As Object, ByVal e As System.EventArgs)
'blah blah
End Sub
End Class
Related
I have an application with 60+ forms and instead of having 60+ copies of the same code in each form, I would like to have one instance of the code that is executed as any form is loading.
The subs are standard:
Protected Overrides Sub OnFormClosing(ByVal e As FormClosingEventArgs)
Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
Protected Overrides Sub OnResize(ByVal e As System.EventArgs)
Protected Overrides Sub WndProc(ByRef m As Message)
I've made countless attempts using classes and modules, but am only able to get the forms that are hardcoded to work as desired.
I have triggered the OnPaint event residing in TitleBar (a non-form class), but I am unable to get TitleBar to apply any customizations to any form. Is there anyway I can circumvent the values in TitleBar's Me and MyBase, and assign them the calling form's values? Or can I get TitleBar to loan out its resources? Any help would be greatly appreciated. BTW, is there a word or phrase for what I'm trying to accomplish?
This has been a long round of trial and error.
Thank you
Create a form as normal and add that common code. In all your other forms, instead of inheriting the standard Form class, inherit the class you just created that contains the common code. That's how inheritance in OOP works.
If you're inheriting a form from a referenced library, you can select Inherited Form in the Add New Item dialogue but that doesn't work to inherit forms in the same project. At least, it doesn't work in an application project, although I haven't tested in a library project. The alternative is to add the form as normal, click the Show All Files button on the toolbar in the Solution Explorer, expand the node for your form, double-click the designer code file to open it and then manually edit the type that your form inherits from, e.g. change this:
Partial Class Form2
Inherits System.Windows.Forms.Form
to this:
Partial Class Form2
Inherits Form1
I have the following classes in my vb.net application:
Form1
Usercontrol1
LnkLabel
Usercontrol1 is a user control , and doesnt contain any extra code. LnkLabel is a class that inherits Forms.Label. Its code is goven below:
Public class LnkLabel
Inherits Label
Sub clk handles me.click
Process.start(text)
End sub
End class
When I add an Instance of LnkLabel to usercontrol1, i get an error "type LnkLabel is not defined"
There are three instances of the error in uc1.designer.vb.How can I solve these Errors?
Note:
Visual Studio 2010
.Net FW 3.5
Edit:
The usercontrol1 donot contain any code that might be causing the error. It is just a new usercontrol added to the project.
LnkLabel is added to UC1 by the designer, not by using code at runtime.
The class name is LnkLabel, and not "LinkLabel".
I find that the easiest way to resolve this type of issue is to open the Designer.vb file directly.
To do this, choose Show All Files from the Project menu, then expand UserControl2. Double-click on the UserControl2.Designer.vb file.
You should also be able to get there by double-clicking on the error in the compile errors list.
Once there, search for the definition of UserControl1 or uc1, whatever it may be called (ensure you are in the type definition area, not the property assignment area).
Looking at the definition may give you an instant clue as to the problem (is it in the wrong namespace; did the name of the user control change after you created it, but the change was not propagated to this form; etc).
If it is not obvious what the issue is, use VS intellisense to help you get the right class. I usually clear the previous type definition and start typing the name I know it should be (i.e. UserControl), then select the appropriate value from Intellisense.
Selecting a different class (or correcting the class selection) will require a change to the control instatiation code and may also require a change to some of the properties (I usually just remove the properties I am unsure of and update the control directly in the designer).
Before you switch back to the designer, ensure that you save your changes and, if possible, compile the app.
I'm using vb.net (vs2010). I'm moving some winforms to a dll. I have a form that inherits from the one which has some subs and functions (like a test app).
My original form is: (.designer)
Partial Class Form1(Of T)
Inherits System.Windows.Forms.Form
....
End Class
Form itself contains code and a toolbar.
My test form is: (.designer)
Partial Class TestForm
Inherits Form1(Of Class1)
I get "Cannot create an instance of Form1`1[T] because Type.ContainsGenericParameters is true" when VS try to load the designer. App is usable. I can build and run the project without errors, but I need to add controls and some code to each new form.
I tried many ways:
Visual Studio 2008 Winform designer fails to load Form which inherits from generic class
How can I get Visual Studio 2008 Windows Forms designer to render a Form that implements an abstract base class?
http://www.codeproject.com/Questions/419770/Csharp-reflection-GetValue-from-a-field-in-generic
http://madprops.org/blog/Designing-Generic-Forms/
All examples are for C#, and I don't know if I'm missing something...
Is this a bad design ? I know this is a VS bug but still it seems everyone fixed it by these links.
EDIT:
I'm building a DLL. Form1 is on this DLL and TestForm is in a new project. Those links works if I'm in the same project (a.k.a. the dll).
Thanks!
Is this a bad design ? I know this is a VS bug
Bad design, not a VS bug. What you are trying to do is fundamentally incompatible with the way the Winforms designer works. It has strong WYSIWYG support, the designer creates an instance of the form's base class and allows code in that base class to run at design time. Which is why, for example, you can set the BackgroundImage property and it is immediately visible in the designer. The Form.OnPaintBackground() method paints it. The designer is not involved at all, it just sets the property.
To make that work, it must be able to create the base class object. It can't in your code, it doesn't know what kind of T to use. Not an issue when you design Form1, the T isn't needed yet since it derives from Form and creating an instance of Form is not a problem. Big issue when you design TestForm.
You'd probably argue that it should use Class1 as the T. It doesn't, the odds that it can use Reflection to discover the generic type argument from TestForm are exceedingly low. That requires the type to be compiled first. That's a chicken-and-egg problem at design time, the TestForm class gets compiled after you design it, not before or while you design.
It's not like you completely cannot use your approach. It builds and runs just fine. You just have to live without design time support for TestForm. That's usually a deal breaker, you have to re-consider your design.
I have created a forms which are derived from another form thus:-
Public Class MyForm
' ...etc
End Class
Public Class MyDerivedForm
Inherits MyBaseForm
' ...etc
End Class
Public Class MyOtherDerivedForm
Inherits MyBaseForm
' ...etc
End Class
This works quite nicely and I can add controls to the derived form using the form designer. But I'd like to move some of the inherited controls around a bit on MyDerivedForm without disturbing MyBaseForm or MyOtherDerivedForm. I can't see any way of doing this on the forms designer.
Is it possible to do this (preferably with the designer but with code if necessary)?
This is not a typical VB.NET problem so not so sure what's going on here. You'll get the lock icon on the inherited controls and a grayed-out Properties window for an inherited control when the Modifiers property of the control in the base class is Private. The Winforms designer observes the accessibility of the base class member. Private members can't be messed with. The default value for Modifiers is Friend in VB.NET, Private in C#.
Make it Friend to allow the derived form class to modify the control properties. If the base form class lives in another assembly then Friend isn't good enough, you'll need Public.
The Anchor property can be an issue, but only if you anchor to the right or bottom. The control has a knack for ending up in the wrong spot when the derived form has a different size from the base form if the control is anchored that way. Simply avoided by not anchoring at the right/bottom in the base class and changing the anchor in the derived class.
In my VB.NET WinForms application I have inherited forms and I can just grab the inherited controls in the designer and move them about as I would with non-inherited controls on the form.
However I have noticed two things in the past that stop this. If you change the position of the controls on the base form, or change some of the positioning properties (such as anchor or docking), then this can (but not always) move your inherited controls. Also I couldn't move some of my inherited controls in an earlier version of .NET (2.0 I believe), but I never figured out the cause for that so I had to resort to changing the locations via the property grid.
I have two Forms, which have similar Functionality (i.e. an amount of similar Controls) but complete different Layout. So the normal inheritedForm (which VS2010 provides) wont work here.
I have tried following:
Public Class BaseForm
Inherits System.Windows.Forms.Form
Friend WithEvents Button1 As System.Windows.Forms.Button
End Class
And in Form1.Designer.vb:
Partial Class Form1
Inherits BaseForm
...
<all Designer generated Code>
...
' Friend WithEvents Button1 As System.Windows.Forms.Button <- remove this Line
End Class
If i compile/execute this, the test form works as expected; But now I am unable to design the form any longer.
If I switch to Design-Mode, it says:
The variable 'Button1' is either undeclared or was never assigned.
So it looks like, the Designer only tries to guess how the Form looks like by inspecting the top-most Class, without compiling the full inheritance-Tree...
Does anyone know a workaround for this?
Thx,
Daniel
I have a feeling you have some existing controls on the base form which you want to bring to the inherited form and then add more functionality of your own. Remember one thing, inheritance in VB.NET is by default set to shadowing, so you can redefine code in your inherited page for the same button to do a different function.
However, I think you forgot the Overridable keyword when declaring the form elements in the parent form. This will help the compiler know that the form can be overridden and allow you to define custom functionality.
Remember, all controls and pages in VB.NET are classes and whatever we learned during OOP classes in college apply here.