My previous article (Windows Form Design at Run Time) explained how to design a form at runtime. I have extended the program to the next advanced version with more functionality. This is one of my favorite articles that I have written. I hope you all like this. Now let's see what's new in my Easy Form Design @ Run Time.
Limitations of my previous article
In my previous article it had the limitation that the user must design and add code for the events like binding the grid and so on. The user can load only one form at a time. Adding a parameter to a SQL query is not possible.
New features in Easy Form Design at Run Time
This has all my previous article features but with more functionality like:
- A new program has 2 parts, the 1st is the Form View part where the user can view all the dynamically created forms by selecting Menu from the tree view.
- The 2nd Form Design part is to Add New/Edit/Save and Open a form dynamically.
- The user does not need to write any code.
- Easy form design.
- The New Feature has options to select a Stored Procedure for their form.
- The user can select a parameter and select a dynamic TextBox control for a parameter that needs to be used in a SQL Server Stored Procedure.
- Save and open the form.
The Easy Form Design at Run Time software application was developed to design your own form using a panel control to add Labels, Buttons, TextBoxes, DataGridViews and so on. The user can select the Stored Procedure to be used for the form for example. Now the user can design there and simply search a form with a TextBox, Button and a DataGridView. For this the user must pass the TextBox as a search parameter to the Stored Procedure and the result must be finally bound to a DataGridView by clicking on the Button. In the form design screen the user can add a TextBox, Label, Button and DataGridView and from the Tools the user can click on the SQL Setting Tool Menu. The user can select his Search Stored Procedure and assign the controls to the parameter matching and finally save the form.
In the main form now the user can view his saved Form Name in the Tree view when he clicks on the menu. His saved form will be displayed. When the user clicks on the button he can view all the details to be loaded from the database using the Stored Procedure that he or she has assigned to the form. This simple C# application allows the user to add:
- Create a new form
- Save a form as a XML file.
- Open a form from a XML file.
- Cut, copy and paste all controls.
- Delete all controls.
- Delete a selected control.
- Add/Change the background color for the form (here a Panel is used as a form).
- Controls can be brought to the front and sent to the back.
- Add a Label Control and using the property window design the Label.
- Add a Button Control and using the property window design the Button.
- Add a CheckBox Control and using the property window design the CheckBox.
- Add a Button Control and using the property window design the Button.
- Add a ComboBox Control and using the property window design the ComboBox.
- Add a DataGridView Control and using the property window design the DataGridView.
- Add a DataTimePicker Control and using the property window design the DataTimePicker.
- Add a Panel Control and using the property window design the ListBox.
- Add a PictureBox Control and using the property window design the PictureBox.
- Add a RadioButton Control and using the property window design the RadioButton.
- Add a TextBox Control and using the property window design the TextBox.
- SQL Setting This is a new feature in this application. Now the user need not write any code here. You can write your Stored Procedure for your database and using the SQL Setting tools menu, you can select your Stored Procedure for your form. Assign the controls property as a parameter to the Stored Procedure.
- Bind/Insert/Edit and Delete Data from database using Stored Procedure.
New Easy Form Design has the following 5 parts to design your from at runtime.
- Form View part
- Form Design part
- SQL Stored Procedure Setting for your Form
- Save Form
- open Existing Form to edit.
Now let's see one by one in detail here.
Section 1st Form View part: In the following image I have pointed to each part by numbers.
- When the user clicks on the “New Form Design” Button, the form will be opened where the user can add, edit, open and save forms. We can see more details in the Form Design part.
- In a Tree View I will list all the saved form names. Whenever users create a new form and save, the saved filename will be listed in the Treeview. When the user clicks on the Treeview Node the related form will be loaded into the right side.
- Here for example we can see that, now the user has clicked on “NewItem” from the Treeview and the related form has been loaded. For this form I have selected the ItemInsert Stored Procedure and passed all the TextBox controls as parameters to the SP.
The following is an animated image that explains it in more detail.
Section 2nd Form Design part
In this application we can see the Toolbar at the left to add controls to the form (here our Panel). The center has a Form (Panel) where the user can add and design their controls. In the right is the Property window to add all the design to the selected controls.
Toolbar: Here we can see all the list of controls that can be added to the form at runtime. There are other features, like Create New Form, Save Form, Open Form, Cut, Copy and Paste Controls. Finally the control you can see is the SQL Setting that is a very important tool to set our form controls with a Stored Procedure to do our CRUD Operations.
When the user clicks on the “New Form Design” button the form design will be opened. You can refer to the preceding image to see how the form design looks. This form plays the main role of creating a dynamic form at runtime. Here users can add New, Edit, Open and Save forms. In the preceding image I have pointed at each part by a number.
- In the left side we have the Tool Menu where the user can add a TextBox, Label, Button, Panel, DataGridView and so on at runtime to design the form.
- The user can design their form here at runtime. The user can drag and drop controls and can resize controls.
- Using the property grid users can change the property of each selected control such as BackColor, FontColor, Text and so on.
- This is to select a Stored Procedure for a form to do CRUD operations and set the parameter of the SP with controls. We will see the details of this part in Section 3rdpart.
Easy Form Design at Run Time will allow users to design a form at runtime, open and save a form and reuse an existing form. The user can add controls at runtime from the Toolbar, design there form, select the Stored Procedure, match and add parameters with controls to perform some action like Select, Insert, Update and Delete.
Now for example the user can add a DataGridView and a Button Control at runtime with a TextBox for searching the user by UserCode and UserName.
Section 3rd SQL Stored Procedure Setting for your Form
After we have designed our form, now it's time to assign our Stored Procedure to our form and pass the control parameters to the SP to do CRUD Operations.
To set the Stored Procedure and assign parameters to the SP, click the SQL Settings menu from the Tool Bar.
When the user clicks on the SQL Setting a new form will be opened as in the following. In the following image I have marked with numbers and let's see each use one by one.
- In the Select Procedure Combo Box I will display all the Stored Procedure names from our database. Note that in our application in the 1Bin folder we can find the “DBConnection.txt” text file that has the default Database Connection String. The user can change the default Connection String depending on the database server name, database name, SQL User id and PWD.
- Once the Stored Procedure for our form is selected, click the Parameter Button. Here we can see I have selected the “USP_USER_SELECT” that will be used in our form to search and bind the user details.
- When we click on the parameter I will display all the parameters for the selected Stored Procedure. Note that everything will be dynamic so the user does not need to add any parameter here. I will list all the parameters that are declared in the Stored Procedure. If the user needs to add or delete any parameter then they can update their Stored Procedure and redesign the form here.
- Select a SQL parameter one by one and click the down arrow button. When the user clicks on the down arrow, the SQL parameter will be displayed in the parameter TextBox.
- In the Control Name List, I will display all the Text Box control names that needs to be assigned to each SQL parameter.
- The same here, select the appropriate control for the SQL parameter and click the 6th button down. The Control Name will be added to the Control TextBox.
- Once the SQL parameter and control has been selected, click the Add Button one by one to add the final SQL parameter list that needs to be saved for our form.
- All the SQL Parameters for the selected Stored Procedure will be added here.
- Confirm the list and click OK to save the form.
Here is the sample GIF image that has an example for the user search bind.
In the Toolbar the user has the option to save the modified form to be viewed from the main screen. You can refer to the following image. When the users click on the Save Toolbar button a list of Main Menu names will be displayed, here all the previously saved file names (I will be using the file name as the Menu name to be displayed in the main screen Treeview). If users want to save the form as a submenu to an existing menu then the user can select the main menu name and enter the new form name to save. If the user wants the form to be a main menu then he can select “Select” from the ComboBox and enter the new form name. Once the form is saved, the menu will be added with the new form name on the main screen.
Note: I will save the form as a XML file. In the application root bin folder you can see the 2 folders “XMLFILE” and “XMLForms”. In the “XMLFILE” folder you can see “NewFormNameList.XML” in this file; I will store all the file names that will be used to list in the main menu TreeView.
In the “XMLForms” folder, for each form you can see 2 XML files. One XML file will be used to store the form control details with all the properties and the other XML file will store each form's Stored Procedure names with parameter details.
Here you can see a sample ItemAdd XML file that has all the control's information with properties like Location, Font Size, FontColor, BackColor, Image and so on.
ItemAdd_query.XML
The ItemAdd_query.XML file has all the details of a form Stored Procedure name with parameters and Control Names.
When a user enters the existing form name to save, then I will overwrite the existing form with the new saved version. I will be saving the forms as XML files.
5th open Existing Form to edit
In the Toolbar the user has an option to open an existing form for modification. You can refer to the following image. When the users click on the Open Toolbar button a list of menu names (which is our form name) will be displayed. The user can select their form name from the list that needs to be opened for modification. If the user knows the form name then they can directly enter the form name in the TextBox and click Open to modify the existing form.
Code Part
The article is an extension of my previous article Windows Form Design at Run Time. Usually I reuse the same code part with a few more new modifications. The form design part is the same as in the previous article. Refer to my previous article about adding controls at runtime and performing drag, drop, resize and delete of controls and so on from my previous article.
In this code part let's see how to do it.
Assign Stored Procedure to form and Add Parameter
In the form design Tool Bar Button Click event I will open the new form to perform the SP Settings.
Form Design SQL Setting Tool Bar Click Event
In the SQL Setting Button Click I will get all the TextBox Control names from the design form and add all the control names to the list and pass the control names list.
- private void toolStripButton1_Click_1(object sender, EventArgs e)
- {
- ControlNames.Clear();
- if (pnControls.Controls.Count > 0)
- {
- foreach(TextBox tb in pnControls.Controls.OfType < TextBox > ())
- {
- ControlNames.Add(tb.Name.ToString());
- }
-
- FrmParameterSetting obj = new FrmParameterSetting(ControlNames);
-
- if (obj.ShowDialog() == DialogResult.OK)
- {
-
- }
- }
- }
FormParameterSetting Form Load event
In FrmParameterSetting Form Load I will get the entire Stored Procedure name and bind to the ComboBox. Bind all the Control Names list to the List view to assign the parameter.
- private void FrmParameterSetting_Load(object sender, EventArgs e)
- {
- LoadSPCopmbo();
- listView2.Items.Clear();
- foreach(string prime in ControlNames)
- {
- ListViewItem lvi = new ListViewItem(prime);
- this.listView2.Items.Add(lvi);
- }
- }
In the LoadSPCopmbo function I will get all the SP Names using the following query. Here I pass the query to the returnDataDatable function.
- public void LoadSPCopmbo()
- {
- comboBox1.AutoCompleteMode = AutoCompleteMode.SuggestAppend;
- comboBox1.AutoCompleteSource = AutoCompleteSource.ListItems;
- String Query = "SELECT name FROM dbo.sysobjects WHERE (type = 'P') ORDER BY name";
- DataTable dt = returnDataDatable(Query);
- comboBox1.ValueMember = "name";
- comboBox1.DisplayMember = "name";
- comboBox1.DataSource = dt;
-
- }
In “returnDataDatable” I will read the Connection String from the text file “DBConnection.ext”. As I explained before in this article, the Connection String will be stored as a text file in the application's root folder.
- public DataTable returnDataDatable(String Query)
- {
- String ConnectionString = ReadConnectionString();
- DataTable dt = new DataTable();
- SqlConnection con = new SqlConnection(ConnectionString);
-
- SqlCommand cmd = new SqlCommand(Query, con);
- cmd.CommandType = CommandType.Text;
- SqlDataAdapter sda = new SqlDataAdapter(cmd);
-
- sda.Fill(dt);
- return dt;
- }
I will check for the text file. If the file exists in the folder then I will read the connection string from the file. If it does not exist then I will write the default Connection String. So kindly check for the “DBConnection.txt” in the root folder and change the Connection String depending on your system database setting.
- <>private String ReadConnectionString()
- <>{
- <> string path = Application.StartupPath + @
- <> "\DBConnection.txt";
- <> String connectionString = "";
- <> if (!File.Exists(path))
- <> {
- <> using(StreamWriter tw = File.CreateText(path))
- <> {
- <> tw.WriteLine("Data Source=YOURDBServerName;Initial Catalog=YOURDBNAME;User id = YOURUSERNAME;password=YOURPASSWORD");
- <> tw.Close();
- <> }
- <>
- <> }
- <> else
- <> {
- <> TextReader tr = new StreamReader(path);
- <> connectionString = tr.ReadLine();
- <> tr.Close();
- <> }
- <> return connectionString;
- <>
- <>}
When the user clicks on the Parameter Buttons, I bind the list of parameters related to the Stored Procedure that has been selected. In the code part you can see I have used the query to get all the parameters for the selected Stored Procedure and bind the final result to the List.
FormParameterSetting Parameter Button Click event
- private void button2_Click(object sender, EventArgs e)
- {
- listView1.Items.Clear();
- String Query = "SELECT p.name AS Name, t.name AS Type, p.max_length AS Length FROM sys.parameters AS p JOIN sys.types AS t ON t.user_type_id = p.user_type_id WHERE object_id = OBJECT_ID('" + txtSPNAME.Text.Trim().ToString() + "')";
- DataTable dt = returnDataDatable(Query);
- foreach(DataRow dr in dt.Rows)
- {
- ListViewItem lvi = new ListViewItem(dr["Name"].ToString());
-
- lvi.SubItems.Add(dr["Type"].ToString());
- lvi.SubItems.Add(dr["Length"].ToString());
-
- this.listView1.Items.Add(lvi);
- }
- }
FormParameterSetting Ok Button Click
Here I will get all the final Stored Procedure names, parameter list and controls for the parameter list and bound the result to the public list class to use in our form design to save the file.
- private void button5_Click(object sender, EventArgs e)
- {
- for (int i = 0; i < listView3.Items.Count; i++)
- {
- ShanuEasyFormDesign.Class.ControlList obj1 = new ShanuEasyFormDesign.Class.ControlList(txtSPNAME.Text.Trim(), listView3.Items[i].SubItems[0].Text.ToString(), listView3.Items[i].SubItems[1].Text.ToString());
-
- ShanuEasyFormDesign.Class.ControlList.objDGVBind.Add(obj1);
- }
- }
Form Design Save
In the save button click I will get all the control details with Property and save the form as XML file.
-
- private void toolSaves_Click(object sender, EventArgs e)
- {
- if (pnControls.Controls.Count > 0)
- {
- frmSave obj = new frmSave();
-
- if (obj.ShowDialog() == DialogResult.OK)
- {
- if (obj.SaveFileName != "")
- {
- Name_Query = Application.StartupPath + @"\XMLForms\" + obj.SaveFileName + "_Query.XML";
- if(!File.Exists(NewFileName_Query))
- {
- if (ShanuEasyFormDesign.Class.ControlList.objDGVBind.Count <= 0)
- {
- MessageBox.Show("procedure and parameter need to be set before save");
- }
- }
- SavetoXML(obj.SaveFileName);
- }
-
- }
- }
- }
Form Open
To open the existing form I will load all the form controls from the selected XML file.
-
- private void toolOpens_Click(object sender, EventArgs e)
- {
- frmOpen obj = new frmOpen();
-
- if (obj.ShowDialog() == DialogResult.OK)
- {
- if (obj.OpenFileName != "")
- {
- xmlFileName = Application.StartupPath + @"\XMLForms\" + obj.OpenFileName + ".XML";
- xmlFileName_Query = Application.StartupPath + @"\XMLForms\" + obj.OpenFileName + "_Query.XML";
- pnControls.Controls.Clear();
- loadXMLFILE();
- }
- }
-
- }
Main Form CRUD operations
In the main form we can see the dynamic CRUD operations will be done for each form. Here is the code that I used to do it dynamically.
TreeView Node Click
When the user clicks on the File Name from the TreeView I will read the appropriate saved XML file and add all the controls to the panel as a form.
- private void treeMenu_AfterSelect(object sender, TreeViewEventArgs e)
- {
-
-
- try
- {
- fileName = Application.StartupPath + @"\XMLForms\" + treeMenu.SelectedNode.Text + ".XML";
- xmlFileName_Query = Application.StartupPath + @"\XMLForms\" + treeMenu.SelectedNode.Text + "_Query.XML";
- pnlMain.Controls.Clear();
- loadXMLFILE();
-
- }
- catch (Exception ex)
- {
- }
- }
FromXml File
I will check for the Button Control and create a dynamic Click event for the Button Control as in the following.
- case "System.Windows.Forms.Button":
- {
- System.Drawing.Color myBackColor = new System.Drawing.Color();
- myBackColor = System.Drawing.ColorTranslator.FromHtml(gParam[8]);
- Button ctrl = new Button();
-
- ctrl.BackColor = myBackColor;
- ctrl.Name = gParam[10];
- ctrl.Location = new Point(System.Convert.ToInt32(gParam[1]), System.Convert.ToInt32(gParam[2]));
- ctrl.Text = gParam[5];
- ctrl.Size = new System.Drawing.Size(System.Convert.ToInt32(gParam[3]), System.Convert.ToInt32(gParam[4]));
- if (gParam[11] == "Front")
- {
- ctrl.BringToFront();
- }
- else
- {
- ctrl.SendToBack();
- }
- ctrl.Click += new EventHandler(control_Click);
- pnlMain.Controls.Add(ctrl);
- }
In the Button Click event I will read the Stored Procedure details from the XML file and bind the final result to the DataGridView. All CRUD operations will be managed in this Click Event.
- private void control_Click(object sender, EventArgs e)
- {
- try
- {
- if (xmlFileName_Query != "")
- {
- XmlDocument xmlQuery = new XmlDocument();
- xmlQuery.Load(xmlFileName_Query);
- XmlNode xnQueryList = xmlQuery.SelectSingleNode("ShanuQuerySave");
- int i = 0;
-
- String txtBox1Name = "";
- String ParameterName1 = "";
- String ControltoBindName = "";
- String Query = "";
-
- foreach (XmlNode xn in xnQueryList)
- {
- Query = xn["ProcedureName"].InnerText;
- }
-
- DataTable dt = new DataTable();
- String ConnectionString = ReadConnectionString();
- SqlConnection con = new SqlConnection(ConnectionString);
- SqlCommand cmd = new SqlCommand(Query, con);
- cmd.CommandType = CommandType.StoredProcedure;
-
- foreach (XmlNode xn in xnQueryList)
- {
- txtBox1Name = xn["cntrlName"].InnerText;
- ParameterName1 = xn["ParameterName"].InnerText;
- ControltoBindName = xn["cntrltoBind"].InnerText;
- Query = xn["ProcedureName"].InnerText;
- if (txtBox1Name != "")
- {
- Control control = returnTextBox(txtBox1Name);
- if (control is TextBox)
- {
- txtBox1Name = control.Text.Trim().ToString();
- }
- }
- cmd.Parameters.AddWithValue(ParameterName1, txtBox1Name);
- }
-
- SqlDataAdapter sda = new SqlDataAdapter(cmd);
- sda.Fill(dt);
- if (dt.Rows.Count > 0)
- {
- if (dt.Columns[0].ColumnName == "Result")
- {
- MessageBox.Show("Record :" + dt.Rows[0].ItemArray[0].ToString());
- return;
- }
- }
-
- if (ControltoBindName != "")
- {
- foreach (Control pnlCntl in pnlMain.Controls)
- {
- if (pnlCntl is DataGridView)
- {
- if (pnlCntl.Name == ControltoBindName)
- {
- DataGridView grid = (DataGridView)pnlCntl;
- grid.DataSource = dt;
- }
- }
- }
- }
- }
- }
- catch (Exception ex)
- {
- MessageBox.Show(ex.Message.ToString());
- }
- }
Conclusion
Note: Things to do before running my application.
Connection String: Before running the application kindly update the Connection String from the application root folder to your local SQL Server database.
I have used SQL Server 2008 R2 and Visual Studio 2010.
Stored Procedures: In the attached Zip file you can find the folder name “SQLScripts” that has all the tables, databases and Stored Procedure Creation script files. Run all the script files one by one to your SQL Server Database.
Run the program
Output
Item Add: I have used the following Sp to insert the Item details.
Note: after an insert I will return the message “Inserted” for confirmation.
-
-
-
-
-
-
-
-
-
- ALTER PROCEDURE [dbo].[USP_Item_Insert]
- (
- @Item_Code VARCHAR(50) = '',
- @Item_Name VARCHAR(50) = '',
- @Price INT=0 ,
- @TAX1 INT=0 ,
- @Discount INT=0 ,
- @Description VARCHAR(50) = '',
- @USR_Name VARCHAR(50) = ''
- )
- AS
- BEGIN
-
- IF NOT EXISTS (SELECT * FROM ItemMasters WHERE Item_Code=@Item_Code and Item_Name=@Item_Name)
- BEGIN
-
- INSERT INTO [ItemMasters]
- ([Item_Code],[Item_Name],[Price],[TAX1],[Discount],[Description],[IN_DATE]
- ,[IN_USR_ID],[UP_DATE],[UP_USR_ID])
- VALUES
- (@Item_Code,@Item_Name,@Price,@TAX1,@Discount,@Description,GETDATE(),@USR_Name
- ,GETDATE(),@USR_Name)
- select 'Inserted' as 'Result'
- END
-
- END
For a better understanding I have added the image as an animated GIF file.
Item Edit: I have used the following Sp to update the Item details.
Note after update I will return the message as “updated” for confirmation.
-
-
-
-
-
-
-
-
-
- ALTER PROCEDURE [dbo].[USP_Item_Update]
- (
- @Item_Code VARCHAR(50) = '',
- @Item_Name VARCHAR(50) = '',
- @Price INT=0 ,
- @TAX1 INT=0 ,
- @Discount INT=0 ,
- @Description VARCHAR(50) = '',
- @USR_Name VARCHAR(50) = ''
- )
- AS
- BEGIN
-
- UPDATE [ItemMasters]
- SET [Item_Name]=@Item_Name,
- [Price]=@Price,
- [TAX1]=@TAX1,
- [Discount]=@Discount,
- [Description]=@Description,
- [UP_DATE]=GETDATE(),
- [UP_USR_ID]=@USR_Name
- WHERE
- Item_Code=@Item_Code
- select 'Updated' as 'Result'
- END
For a better understanding I have added the image as an animated GIF file.