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/
Related
I have two forms in my project (a simple game for kids). The first one is the start menu and the second one is the game. Now, when I click on New Game, I want the second form to open within the first one. I did that by using the following code:
private Form activeForm = null;
private void openChildForm(Form childForm1)
{
if (activeForm!=null)
{
activeForm.Close();
}
activeForm = childForm1;
childForm1.TopLevel = false;
childForm1.FormBorderStyle = FormBorderStyle.None;
childForm1.Dock = DockStyle.Fill;
panel1.Controls.Add(childForm1);
panel1.Tag = childForm1;
childForm1.BringToFront();
childForm1.Show();
}
Now the second form opens within the first one, but it doesn't work properly. In my second form I have a picturebox, which is supposed to move when the user presses on one of the arrow keys. But it won't move.
Any suggestions what should I do?
P.S.
I'm a beginner and this is a school project. My teacher showed us only one way of opening a form:
Form2 objForm2 = new Form2();
objForm2.Show();
but since it is a very ugly method of getting the job done, I wanted to do it better.
I'm using Visual Studio 2019
I would suggest you to use a so called UserControl it's basically that what the name says: It's a custom windows forms control, witch has it's own child controls -> Just Like a form.
If I were to navigate between 2 forms (or more), it would be like this:
Main Menu to second form:
Form2 form2 = new Form2(this) // Instantiate form and pass form data to next form
Hide();
Second form:
Form1 form;
public Form2(Form1 form1)
{
this.form1 = form1; //Take in previous form's data
}
Navigating forward will Hide() the current form while navigating backwards will Close() the current form.
But what if I am in the 3rd, 4th... nth form and I wish to go back to the main menu? Is there some kind of way to close all of my hidden forms?
Or is there a proper method to navigate between forms?
In my opinion you should use Interfaces to change data between forms. This let's you stay more independent and your Form2 just get the data it needs. For example:
public interface IForm1 //You should find better naming
{
void Edit(); //Method for edit some data
List<T> DataList {get;} //List with some relevant data
}
public Form Form1 : IForm1
{
public void Edit(){ //Your edit logic}
public List<T> DataList {get{return myGrid.DataSource as List<T>;}}
}
public Form Form2
{
private IForm1 formData;
public Form2(IForm1 formData)
{
formData = formData;
}
}
Further i would think about your idea to have so much forms. I think one MainForm with a TabControl as first element is better way to go in many cases. You can create a UserControl for each TabPage and just switch the TabPage instead of poping up Forms all the time.
UPDATE
This Picture maybe clarify what i mean. The TabPageHeader are all invisible (in image i make it visible for clarification). If Login succeed you just switch the TabPage.
TabControl.SelectedTabPage = tabPageMainScreen;
So it feels more fluent to the user and you don't have the problem you describe. But i would recommend to separate the Form by different UserControls to keep it simple.
UPDATE 2
On Winforms you can hide the TabHeader as suggested in this post.
Example:
tabControl.ItemSize = new Size(0, 1);
tabControl.SizeMode = TabSizeMode.Fixed;
It's a bit ugly that the default TabControl don't has regular way but it works fine.
I would create a view model from the data in the first form and then supply it in a method on the second form.
public class Form1ViewModel {
public int Age {get; set;}
public string Name {get; set;}
}
//method on Form1
public void NavigateToForm2()
{
var vm = new Form1ViewModel{ Age = 32, Name = "Test name"};
var form2 = new Form2();
form2.SetViewModel(vm);
form2.Show();
}
Also to close the forms take a look at this link.
I would recommend taking a look into MVVM pattern because that handles the navigation, instantiation of the forms (views). A library to start with is mvvmfx. There are also other libraries for MVVM.
While Sebi and Mihail has given great ways for a proper navigation, I have did some practice on my own and found several solutions.
As what Sebi mentioned, a TabControl with one main form is the better way to go in many cases as it is more fluent, does not have forms popping up all the time.
Another way is to only preserve the instance of your parent(main) form:
Navigating from a child form to another will pass the parent form and values of your data (if required), before closing the form (Once closed, all resources created is disposed).
However in some cases where you need to maintain the values for a previous child form (So that all user input does not need to be re-entered again), You have to also pass the child form and hide it instead of closing it.
One thing that confused me when I opened the question was that I had initially thought that navigating forward in forms should always use Hide();, and not Close();.
To close all forms except the main form (Might be useful for those who have a similar design concept as mine):
List<string> currentform = new List<string>();
foreach (Form form in Application.OpenForms)
{
if (form.Name != "Form1")
{
currentform.Add(form.Name);
}
}
foreach (string formName in currentform)
{
Application.OpenForms[formName].Close();
}
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 have 2 project in 1 solution and each project have 1 form. In form 1 i have label and button, and i want when i click on button it will show in form 2 labeltext in form 1.
my code in form 1:
WindowsFormsApplication1.Form1 layarForm1 = new WindowsFormsApplication1.Form1();
layarForm1.Show();
layarForm1.LabelText = no_antrian.Text;
//layarForm1.LabelText = this.Refresh();
form2(in other project but in same solutions, and i have reference to form 1):
public string LabelText
{
get
{
return this.ruang_1.Text;
}
set
{
this.ruang_1.Text = value;
}
}
my code work for first time but when i click button again it will show new form. is there any ways that label text in form 2 will refresh after button click. And i dont want to use dispose form because in form 2 i have video played that will start again if i use dispose() and show()
Two projects = 2 executable you need to use shared memory or named pipes to send the data across from one exe to another, or use winapi such as SendMessage once you get the window handle of the other window and the find the child window handle via EnumChildWindows.
Why not use the two forms in the same project?
The problem is every time the button is clicked, an instance of the form is created. You need to check whether the form is already open and if not create an instance, show the form and update the label.
If the form is already open, all you need to do is to update the label and set focus on the form.
You can use Application.OpenForms to iterate through all one forms and check whether the form is in that collection.
Something like
foreach (Form frm in WindowsFormsApplication1.OpenForms)
{
if (frm.Name == "MY_FORM_NAME") then
frm.LabelText = no_antrian.Text;
else
{
WindowsFormsApplication1.Form1 layarForm1 = new
WindowsFormsApplication1.Form1();
layarForm1.Show();
layarForm1.LabelText = no_antrian.Text;
}
}