I have a Window Form App project. At the moment all of my code is in Form1.cs file which is the default file. Now I have about 1300 lines of code in this single file. I want to break down this one file code into several files and I want to use the "partial" key word (I don't want to do anything drastic). So how should I add the files
Right click project name->add->new item ->class results into class1.cs, class2.cs and so on
But this file converts to a form form file after compilation. What's the correct way of adding so that the new file integrates with my existing project Form1.cs and Form1.cs[Design]?
You have to keep the namespace, the class name and mark it with partial. The file name is not really important for it to work, but it's a good practice so that the developers can identify rapidly the contents of the file.
Form1.cs
namespace TheSameNamespace
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
}
// other definitions
}
Form1.Designer.cs
namespace TheSameNamespace
{
partial class Form1
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
// the rest of the designer class
}
}
Form1.Calculations.cs
namespace TheSameNamespace
{
partial class Form1
{
// calculation methods definitions
}
}
Form1.EventHandlers.cs
namespace TheSameNamespace
{
partial class Form1
{
// event handlers definitions
}
}
and so on...
The partial keyword is primarly for generated files, which can be extended by your own code - there is no use in splitting a single bloated class into multiple partials, but if you really want to do it then you have to:
Create a new class.
Rename the class to match your own class (Form1.xxx.cs)
Use the partial key-word and adjust the name and the namespace.
To clearify:
Form1.cs
public partial class Form1 { /* ... */ }
Form1.somepart.cs
public partial class Form1 { /* ... */ }
Related
You should be able to create a generic form:
public partial class MyGenericForm<T> :
Form where T : class
{
/* form code */
public List<T> TypedList { get; set; }
}
Is valid C#, and compiles. However the designer won't work and the form will throw a runtime exception if you have any images stating that it cannot find the resource.
I think this is because the windows forms designer assumes that the resources will be stored under the simple type's name.
Yes you can! Here's a blog post I made a while ago with the trick:
Designing Generic Forms
Edit: Looks like you're already doing it this way. This method works fine so I wouldn't consider it too hacky.
I have a hack to workaround this, which works but isn't ideal:
Add a new class to the project that inherits the form with its simple name.
internal class MyGenericForm:
MyGenericForm<object> { }
This means that although the designer is still wrong the expected simple type (i.e without <>) is still found.
You can do it in three steps.
1) Replace in Form1.cs File
public partial class Form1<TEntity, TContext> : Formbase // where....
2) Replace in Form1.Designer.cs
partial class Form1<TEntity, TContext>
3) Create new file : Form1.Generic.cs (for opening design)
partial class Form1
{
}
If paleolithic code doesn't affraid you
public static MyForm GetInstance<T>(T arg) where T : MyType
{
MyForm myForm = new MyForm();
myForm.InitializeStuffs<T>(arg);
myForm.StartPosition = myForm.CenterParent;
return myForm;
}
Use it
var myFormInstance = MyForm.GetInstance<T>(arg); myFormInstance.ShowDialog(this);
I get an error saying "Missing partial modifier on declaration of type 'projectName.Main'; another partial declaration of this type exists.
From what i can read about this error, its because i have classes with same name. It does work if i modify the main class to public partial class Main : Form but i want to know why it gives me this error. I need to initializeComponent within Main(), tried creating a method start() and then calling main.Start() in a load event, but then the form loads blank.
namespace projectName
{
public class Main : Form
{
public Main() // Method: Starts the main form
{
InitializeComponent();
}
public void Main_Load(object sender, EventArgs e)
// On load of main class, handle events and arguments
{
Main main = new Main();
main.getCurrentDomain();
}
public void getCurrentDomain() // Method: Get current domain
{
Domain domain = Domain.GetCurrentDomain();
}
} // Ends the main class
}
Assuming this is a Windows Forms app, the problem is that the Visual Studio WinForms designer has created another file (e.g. Main.designer.cs) with:
public partial class Main : Form
to contain designer-generated code.
Your partial class source is effectively merged with that - but it can only happen when both source files declare that the class is partial. Otherwise, you're just trying to declare two classes with the same name in the same namespace, which is prohibited by C#.
There is another file with the name .designer.cs. This file contains the partial definition of class and that is where your InitializeComponent function is defined. You need to add partial modifier to your class.
Here's my wish to create something abstract in WPF. You've got a main window (called main for example, even if it's not correct we don't care) with two buttons. Those two buttons have the same function : they open a new window, the same for both of them, but with different things inside. So I decided to create an abstract class to rule them like that :
public abstract (partial ?) class A : Window
{
public A()
{
InitializeComponent(); // Not sure about that, it's kinda weird to use it here no ?
}
...
}
public partial class B : A
{
public B()
{
InitializeComponent(); // Since it's already in A I shouldn't have to use it here right ?
}
...
}
public partial class C : A
{
public C()
{
InitializeComponent(); // Same thing here...
}
...
}
Debugging gives me something like : "error CS0263: Partial declarations of 'namespace.B' must not specify different base classes".
Removing 'partial' from A class gives : "error CS0260: Missing partial modifier on declaration of type 'namespace.A'; another partial declaration of this type exists".
I know that 'partial' specifies if a class has another part of her somewhere else (like the xaml file beside the cs one), so I guess the abstract class has to be partial too since it contains my controls. Maybe the B class shouldn't be partial ?
I know (memories) it works with Windows Forms, but there's no xaml files so it's easier, and I didn't find any useful tips. I think I understood that this problem occurs when I don't change something in my xaml file, which doesn't works as simply as "class : abstract class". Maybe the subclass thing ?
Please note that I'm a beginner in WPF apps, so I thank you in advance if your answer is as detailed as possible.
Thanks !
You need to define your base class all in code without using XAML :
Code for class A :
public abstract class A : Window { }
Code for class B :
public partial class B : A
{
public B()
{
InitializeComponent();
}
}
xaml for class B :
<yourNamespace:A x:Class="yourNamespace.B"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:yourNamespace="clr-namespace:yourNamespace"...
A C# partial class is one that is defined over two or more source files. The other 'part' of Window is generated by Visual Studio, and includes things like InitializeComponent()
If you want a base Window class, then it has to be defined entirely in code, and have no XAML component. It will then no longer be a partial class.
public abstract class WindowA : Window
{
// define base methods here
}
Then you can derive WindowB from WindowA:
public partial class WindowB : WindowA
{
public WindowB()
{
InitializeComponent();
}
}
But you also need to do it in the other 'part', i.e. in XAML, so in WindowB's XAML file, the root Window tag needs to be changed to:
<wpfApp:WindowA x:Class="WpfApp.WindowB"
wpfApp:WindowA ="clr-namespace:WpfApp"
(you'll need to change the namespace appropriately)
This will generate the other 'part' deriving from WindowA, so there will be no inconsistency.
The InitializeComponent() method should be called in each derived class' constructor, as it's specific to that class, i.e. in this case, the other 'part' is generated from the XAML, and defines an InitializeComponent() with resourceLocator code that specific to WindowB.
I am making a MessageBox like class (MessageBoxCustom).
I would like to have a Form with designer support in a separate file so I can modify the appearance through Visual Studio (MessageBoxCustomDialog ).
I would also like to make this MessageBoxCustomDialog unreachable by code outside MyMessageBox and I'm nesting MessageBoxCustomDialog. I would like to move it in a separate file so I'd have designer support. Maybe using a partial class? How would the hierarchy go?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace System.Windows.Forms
{
public static class MessageBoxCustom
{
public static void Show()
{
(new MessageBoxCustomDialog()).ShowDialog();
}
private class MessageBoxCustomDialog : Form
{
}
}
}
The Visual Studio Designer can not help you design nested classes. It is just not made for that. It checks the type of the first outermost class in the file and then decides which designer to use.
If it is just about designing the layout of the form I would recommend to design it as usual. When you finished your project you can then surround the class by the outer class (in both files) and make it private.
When you finshed your work just copy and paste the dialog class into the outer class and make it private. If you have to rework the design it is again just copy and paste.
MessageBoxCustomDialog.cs:
namespace System.Windows.Forms
{
// make sure this is the first class in the file (required by designer)
public partial class MessageBoxCustomDialog : Form
{
public MessageBoxCustomDialog()
{
InitializeComponent();
}
}
public static partial class MessageBoxCustom
{
public static void Show()
{
new MessageBoxCustomDialog().ShowDialog();
}
// put the MessageBoxCustomDialog class here when you are done
}
}
MessageBoxCustomDialog.Designer.cs:
namespace System.Windows.Forms
{
partial class MessageBoxCustomDialog
{
...
}
partial class MessageBoxCustom
{
// put the MessageBoxCustomDialog class here when you are done
}
}
Make your MessageBoxCustomDialog a private partial inner class
private partial class MessageBoxCustomDialog : Form
{}
You must make MessageBoxCustom partial having same scope of MessageBoxCustomDialog
File 1
using System.Windows.Forms;
namespace System.Windows.Forms
{
public static partial class MessageBoxCustom
{
public static void Show()
{
(new MessageBoxCustomDialog()).ShowDialog();
}
private partial class MessageBoxCustomDialog : Form
{
}
}
}
File 2
using System.Windows.Forms;
namespace System.Windows.Forms
{
public static partial class MessageBoxCustom
{
private partial class MessageBoxCustomDialog : Form
{
// designer code
}
}
}
You may see this link http://msdn.microsoft.com/en-us/library/wa80x488.aspx [Restrictions section]
You should be able to create a generic form:
public partial class MyGenericForm<T> :
Form where T : class
{
/* form code */
public List<T> TypedList { get; set; }
}
Is valid C#, and compiles. However the designer won't work and the form will throw a runtime exception if you have any images stating that it cannot find the resource.
I think this is because the windows forms designer assumes that the resources will be stored under the simple type's name.
Yes you can! Here's a blog post I made a while ago with the trick:
Designing Generic Forms
Edit: Looks like you're already doing it this way. This method works fine so I wouldn't consider it too hacky.
I have a hack to workaround this, which works but isn't ideal:
Add a new class to the project that inherits the form with its simple name.
internal class MyGenericForm:
MyGenericForm<object> { }
This means that although the designer is still wrong the expected simple type (i.e without <>) is still found.
You can do it in three steps.
1) Replace in Form1.cs File
public partial class Form1<TEntity, TContext> : Formbase // where....
2) Replace in Form1.Designer.cs
partial class Form1<TEntity, TContext>
3) Create new file : Form1.Generic.cs (for opening design)
partial class Form1
{
}
If paleolithic code doesn't affraid you
public static MyForm GetInstance<T>(T arg) where T : MyType
{
MyForm myForm = new MyForm();
myForm.InitializeStuffs<T>(arg);
myForm.StartPosition = myForm.CenterParent;
return myForm;
}
Use it
var myFormInstance = MyForm.GetInstance<T>(arg); myFormInstance.ShowDialog(this);