I am using a base form that has a menu on it so that I don't have to re-do the code for the whole application.
Essentially this form is called StudentBase.cs
Then I have another form called StudentProfile that inherits from StudentBase
public partial class StudentProfile : StudentBase
{
public string selectedPage;
}
This then inherits the menu that is in StudentBase and I don't have to re-do the menu.
On the menu, there are buttons for the individual forms.
So let's say I press on Student Profile I use this to navigate:
private void btnProfile_Click(object sender, EventArgs e)
{
//I don't want the page to reload if it is the current page
if (selectedPage != "Profile")
{
StudentProfile profile = new StudentProfile();
profile.Show();
this.Hide();
}
}
Doing this produces a very laggy result, as well as it looks very glitchy
I override selectedPage in the child forms so in the case of StudentProfile I use:
private void StudentProfile_Load(object sender, EventArgs e)
{
selectedPage = "Profile";
}
I have tested this on my friend's code and his navigation works without lag or glitch. He didn't do the inheritance on the form
The problem with your inheritance solution is that when you create an instance of StudentProfile you also create an instance of the StudentBase form. You show this new instance and hide the old one. You now have two instances of StudentBase (one visible and one hidden). As you open more forms from your menu, you get more instances of StudentBase in memory. Even though they are hidden they still consume resource. This would explain the result you see.
I suggest you do as your friend, which is by the way the typical way child forms are handled from a main menu.
So, I couldn't properly figure out how to use the UserControls. I put it on my to-do list so I can try that at the end of the project if I still have time left.
But, I figured out why it was taking so long to move from one navigation to the other.
I was selecting the student details in the base form using
Student student = new Student();
Student studentDetailsFound = student.GetStudent(2);
I never stopped it from selecting from the database every time it navigates to a new form, thus, the two-second delay every time.
So there were two options to fix this: Static variables or caching.
I used the latter and now it switches to the pages rather fast.
By adding a transition on the form, it made it a lot smoother on the eyes.
Also note: if you are getting the data like I am you should first wait for the designing of the form to finish. So put the GetStudent part into this if:
if (this.Site == null || !this.Site.DesignMode)
{
studentDetailsFound = GetStudent();
}
Related
Hello Everyone
In the following, I am going to give you a routh idea of what I am trying to accomplish with the program I am trying to code at the moment bevor describing the problem I am struggeling to solve. Thanks for your help!
The Program
Purpose
Timers. Multiple of them. Each timer should be displayed on an individual form, being controlled by individual buttons and having a unique design, once again set up by user settings.
Layout
The program itself should be made up by one main form, containing all "start" and "stop" buttons for each timer. However, the timer forms should be open at all time. Meaning, once the user has changed the properties, all timer forms should be closed again and depending on the settings new forms should open.
Question
In generell, I know how to open a form in such a way to change properties and componants from another form. Example:
namespace example
{
public partial class Form1 : Form
{
Form2 timerForm1;
private void Form1_Load(object sender, EventArgs e)
{
timerForm1 = new Form();
timerForm1.Show();
}
//now you are able to access Form2 in different functions, like:
{
timerForm1.label1.Text = "00:02:56";
}
}
}
However, I need to open as many forms as the user declares, meaning I can not set up variables in fore hand. However, I need to access those opend forms just like in the given example.
I would like to store the different, user declared timers inside an array or list if possible, if there is a smarter, easier or faster way i can adapt and change it to whatever is required to get it working.
I didn't really understand what or if you have an issue with the timers. But controlling various amount of forms from each individual is not that hard.
As I understand that you want to control various amount of Form2 instances from one Form1. In that case you can make a List of Form2 and add each Form2 you creat to that list.
I'm trying to build an Application UI using Winform for which will be having multiple pages inside it. Say software will be asking for a Login credentials on startup and then landing in a Dashboard. Then the user will have the option to go different pages like: Page1 - Page2 - Page3.
Now I'm planning to make one Form and all these pages will be separate UserControls. So as per requirement I will be changing the visibility of these UserControls.
Now to do this I'm putting the below code inside Form1.cs
ControlLogin ucLogin = new ControlLogin();
ucLogin.Location = new System.Drawing.Point(12, 67);
this.Controls.Add(ucLogin);
This works fine. But while opening any UserControl from this ControlLogin.cs how will I add the new UserControl (say Page1Control) to the list of Form1?
You need to develop some transaction logic for your pages. I suggest that on your main form you use a panel to use as container. In this container you will place current user control, the one that user selects.
For example:
internal void ReplaceUserPage(Control container, UserControl userRequest)
{
if (container.Controls.Count == 1)
{
container.Controls.RemoveAt(0);
}
container.Controls.Add(userRequest);
userRequest.Dock = DockStyle.Fill;
}
If you don't have dynamic pages, you can make all of them singletons. This way, instance of each will be created on demand and live in memory, ready to reuse. So, when user clicks on a menu or a button to open the page, you can do
UserControl requested = Page1Control.GetInstance();
ReplaceUserPage(container, requested);
With singleton, you don't even need to keep list of your controls. I don't say that this is best or perfect or one-fits-all way. There are many control transaction approaches. It depends on system complexity and other factors.
The basic layout you chose looks fine to me.
Your actual question seems to be: How to reference the form from those UCs?
This is closely related to the questions: How to reference a form or parts of it from other forms? This has been asked here very often..
Here is what I suggest you should do:
Create a public function for opening each of your UCs openLogin, openPageOne..
Change the constructors of each UC to include a Form1 as a parameter (assuming your form has the default name) and call it accordingly like this: ControlLogin ucLogin = new ControlLogin(this);
In the UCs constructors you want to store the passed in form in a class variable.
In the form you write:
public void openLogin(Form1 f)
{
ControlLogin ucLogin = new ControlLogin(this);
ucLogin.Location = new System.Drawing.Point(12, 67);
this.Controls.Add(ucLogin);
}
public void openPageOne(Form1 f)
{
..
}
And in the UC(s):
public ControlLogin(Form1 form1)
{
InitializeComponent();
mainForm = form1;
}
Form1 mainForm = null;
Now you can reference all public fields and methods in the form, maybe like this
if (logingIsOK) mainForm.openPageOne();
I am developing a very basic application Windows Form Application in c# that inserts values into a SQL database.
I have four separate forms
one for inputting customer details
one for inputting any transaction details
one for searching customers/transactions respectively.
What is the best way link all four forms together? I'm only just getting into C# so the most basic way possible would be ideal.
The way I see it working in my head is that you run the program and end up on one screen which shows four buttons for the four corresponding forms. When you press the button a separate window opens showing the insert forms. You can then close the form to return to the Main Start Screen
What would be the basic code for this in C#? For examples sake lets say the 5 different layouts are
Main (Containing the buttons)
TransactionEntry
AddressEntry
TransactionSearch
AddressSearch
Okay, here is an example of how I would do it. On the main form on button click event:
frmSecondForm secondForm = new frmSecondForm(this); //"this" is passing the main form to the second form to be able to control the main form...
secondForm.Show();
this.Hide();
One your Second Forms constructor code:
Form frmHome;
frmSecondForm(Form callingForm) //requires a calling form to control from this form
{
Initialize(); //Already here
frmHome = callingForm as frmMain;
}
Then on the second form's closing unhide the main form:
frmSecondForm_FormClosing()
{
frmHome.Show();
}
So all in all, if you needed to pass data between the forms just add it as a parameter on the second form.
Again, I would consider placing your data collection into a repository package (folder) and class, then create a User.cs class that will hold all of the information you keep in the database.
Hint: Right click your top level item in solution explorer and go to New -> Folder. Name it Repo.
Right click that folder and go to New -> Class and name it UserRepo.
In here build functions to collect the data from the databases.
On your main form's constructor area, call the class (repo).
private Repo.UserRepo userRepo;
frmMain_FormLoad()
{
userRepo = new Repo.UserRepo();
}
Then on log in button click:
private button1_ClickEvent()
{
if(userRepo.isValidLogin(userNameText, passwordText))
{
//Do stuff
}
}
for userRepo.isValidLogin()
public bool isValidLogin(String username, String password)
{
bool isValid = false;
//Write up data code
return isValid;
}
From the Main form use eg:
TransactionEntry trans = new TransactionEntry();
trans.ShowDialog();
.ShowDialog() will show the new form, but will halt any code executing on the Main form until you close it
(This assumes your forms are all in the same solution)
You could try the MDI (Multiple Document Interface) way, here is a nice tutorial: http://www.dreamincode.net/forums/topic/57601-using-mdi-in-c%23/
I've WinForms program with 2 GUI's. I work with one GUI and open another GUI using
var gui = new FormGui("SomeVar", someOthervar);
gui.ShowDialog();
I use ShowDialog() or Show() depending on what I need to get. When I'm done I would like to pass results (sometimes it's 2 strings, sometimes it's more then that) back to the Mother GUI which called Child GUI.
What's the best way to do that? I was thinking about using global variables but not sure if that's best approach?
You can create properties on your FormGui and set those within the form. When you're done with the form, you can grab those properties from your reference to the form:
var gui = new FormGui("SomeVar", someOthervar);
gui.ShowDialog();
var result = gui.Result;
EDIT: Regarding your comment:
Say your child form has some button on it or something that the user can interact with. Or if there's a close button they click on:
private void buttonCloseClick(object sender, EventArgs e)
{
this.Result = new ResultObject()....
}
EDIT #2 Regarding your second comment:
Yes, on your FormGui class, you need to define an object called Result:
public partial class FormGui : Form
{
public ResultObject Result {get;set;}
}
ResultObject is just something I'm making up. The point being that you're in control of FormGui, so you can add any property you want, and then access it on the FormGui object.
You can add a property on the FormGui class that contains the results you want to use in the parent form.
Also, you can use the result of ShowDialog() to pass information back as well - although this is limited values of the DialogResult enum.
You can call with ShowDialog, on the child window, use a new public property to set the result, and when you close the dialog the parent GUI should be able to see the result in the next code line.
The answer by BFree is enough for your task
I am suggesting easy way to add properties to all forms
Make a new class extend it with System.Windows.Form
public class Form : System.Windows.Forms.Form
{
//add properties
}
Check your properties in your forms
I'm rewriting an old application and use this as a good opportunity to try out C# and .NET development (I usually do a lot of plug-in stuff in C).
The application is basically a timer collecting data. It has a start view with a button to start the measurement. During the measurement the app has five different views depending on what information the user wants to see.
What is the best practice to switch between the views?
From start to running?
Between the running views?
Ideas:
Use one form and hide and show controls
Use one start form and then a form with a TabControl
Use six separate forms
Creating a bunch of overlaid panels is a design-time nightmare.
I would suggest using a tab control with each "view" on a separate tab, and then picking the correct tab at runtime. You can avoid showing the tab headers by putting something like this in your form's Load event:
tabControl1.Top = tabControl1.Top - tabControl1.ItemSize.Height;
tabControl1.Height = tabControl1.Height + tabControl1.ItemSize.Height;
tabControl1.Region = new Region(new RectangleF(tabPage1.Left, tabPage1.Top, tabPage1.Width, tabPage1.Height + tabControl1.ItemSize.Height));
What I do is to have a Panel where your different views will sit on the main form.
then create user controls for your different views.
Then when I want to switch between a'view' you dock it to Panel on the main form.. code looks a little like this.
i preffer this because you can then reuse your views, like if you want to open up a view in a tab you can dock your user controls inside tab pages.. or even inherit from
tabpage instead of usercontrol to make things a bit more generic
public partial class MainForm : Form
{
public enum FormViews
{
A, B
}
private MyViewA viewA; //user control with view a on it
private MyViewB viewB; //user control with view b on it
private FormViews _formView;
public FormViews FormView
{
get
{
return _formView;
}
set
{
_formView = value;
OnFormViewChanged(_formView);
}
}
protected virtual void OnFormViewChanged(FormViews view)
{
//contentPanel is just a System.Windows.Forms.Panel docked to fill the form
switch (view)
{
case FormViews.A:
if (viewA != null) viewA = new MyViewA();
//extension method, you could use a static function.
this.contentPanel.DockControl(viewA);
break;
case FormViews.B:
if (viewB != null) viewB = new MyViewB();
this.contentPanel.DockControl(viewB);
break;
}
}
public MainForm()
{
InitializeComponent();
FormView = FormViews.A; //simply change views like this
}
}
public static class PanelExtensions
{
public static void DockControl(this Panel thisControl, Control controlToDock)
{
thisControl.Controls.Clear();
thisControl.Controls.Add(controlToDock);
controlToDock.Dock = DockStyle.Fill;
}
}
Tabbed forms are usually good... but only if you want the user to be able to see any view at any time... and it sounds like you might not.
Separate forms definitely works, but you need to make sure that the switch is seemless...if you make sure the new form appears the same exact size and location of the old form, it will look like it thew same for with changing controls.
The method I often use is actually to pre-setup all my controls on individual "Panel" controls and then show and hide these panels as I need them. The "Panel" control is basically a control container... you can move the panel and all controls on it move relative. And if you show or hide the panel, the controls on it do the same. They are great for situations like this.
The method I often use is actually to
pre-setup all my controls on
individual "Panel" controls and then
show and hide these panels as I need
them.
Instead of making each view a panel within a single form you could make each view a UserControl. Then create a single form and write code to create and display the correct UserControl in the Form and to switch from one to the next. This would be easier to maintain because you will have a separate class for each view instead of a single Form class with 6 panels each with their own controls -- that seems difficult and error prone to maintain.
I would also check out Composite Application Guidance for WPF or Smart Client Software Factory