Introduction
I started to write a large program that will contain some good functions to be able to code fields for documents and retrieve them easily by searching fields and/or OCRed body of the documents. My first two steps of the application about done. I would like to share one of the components that I wrote called "Field List" control
This control runs of a file with "lst" extension which carries a very simple structure in text format.
Please check out the Video Clip of this code here,
Points of Interest
This article targets beginners to learn about "creating controls during runtime" which also includes List<string> array, splitting string and other simple samples of C# programming. If enhanced, this also could be used for any programs that needs unlimited field entry.
Components
I will include one component in this article. Please download the code to see the working sample.
"FieldList" control has a Vertical Scroll bar and a container that labels, textboxes and/or drop-down boxes created during runtime. So, this is one of the useful things people might learn. How to create controls in runtime and get information from them. Following image shows the text file this control uses. Creating the text file is up to you. I am using another form that I created. First line of the code has a number that tells the control how many other lines of texts are being used for header purposes. Headers are not used by the control, they are ignored. Also, if you have a drop down menu, you have to use "@" sign to split them. You still identify the field name with the first item of the line. Example,"States@Alaska@Arizona@Alabama" your field name is "States" and drop down items are Alaska, Arizona and Alabama.
The Code
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
namespace FieldList
{
public partial class FieldList : UserControl
{
// Fields
// private int intFieldCount; // Number of fields will be
set
private
const int
BoxHeight = 20; // Height of the Textbox
public
FieldList()
{
InitializeComponent();
}
// We get the
path of the 'lst' file and the lines will be skipped at the top of that file
// There
might be some user notes on the top that program should skip at streamread
public void LoadFields(string
FieldFilePath)
{
// Check
the path
if
(File.Exists(FieldFilePath) != true)
{
throw
new Exception("'Field List' File Can not be found!");
}
string
LineData; // Line datab from 'lst' file
string
LabelText; // Field label text
string
ControlBoxName; // Combobox and textbox names created
with this
string[]
SplitText; // Splitter
int
ControlCount = 0; // This calculates the 'top' for
the controls
int
ii = 0; // Loop to bypass top lines of the 'lst' file
int
SkipFirstLines;
//
panel1.Top = 0; // Set container's 'top' value
panel1.Width = (this.Width - 10) - SCRBar.Width; // Set container's 'width' value
// Open
Stream to tread
StreamReader
CurrentFields = new StreamReader(FieldFilePath);
// Find
out how many lines wil be skipped
SkipFirstLines = Convert.ToInt32(CurrentFields.ReadLine());
// Set
fields
for
(ii = 0; ii < SkipFirstLines; ii++) // First two
lines are not fields
{
LineData =
CurrentFields.ReadLine();
}
while
(CurrentFields.EndOfStream != true)
{
LineData = CurrentFields.ReadLine();
SplitText = LineData.Split('@');
LabelText =
SplitText.GetValue(0).ToString();
ControlBoxName =
LabelText.Replace(' ', '_'); // Replace spaces
with
//
underscores for text and combo box names
if
(ControlCount > 0)
{
ControlCount = ControlCount
+ (BoxHeight + 2); // Encrement 'top' value
}
else
{
ControlCount = 1; // This is set to one only once.
//
Code will not come here the second time
}
if
(SplitText.Count() > 1)
{
//
Drop Down Control
ComboBox NewComboBox = new ComboBox();
NewComboBox.Width =
((panel1.Width / 3) * 2) - 5;
NewComboBox.Height =
BoxHeight;
NewComboBox.Left =
(panel1.Width / 3) + 5;
NewComboBox.Top =
ControlCount;
for
(ii = 0; ii < (SplitText.GetUpperBound(0)); ii++)
{
NewComboBox.Items.Add(SplitText.GetValue(ii + 1));
}
NewComboBox.Name = "cmb" + ControlBoxName;
panel1.Controls.Add(NewComboBox);
NewComboBox.SelectedIndex =
0;
}
else
{
//
Text Control
TextBox NewTextBox = new TextBox();
NewTextBox.Width =
((panel1.Width / 3) * 2) - 5; // Space little less
than 2/3
NewTextBox.Height =
BoxHeight;
NewTextBox.Left =
(panel1.Width / 3) + 5; // Start next to label
NewTextBox.Top =
ControlCount;
NewTextBox.Name = "txt" + ControlBoxName;
panel1.Controls.Add(NewTextBox);
}
CreateLabel(ControlCount, LabelText);
panel1.Height = ControlCount +
32;
}
ScrollSet();
CurrentFields.Dispose();
}
private
void CreateLabel(int
TopValue, string LabelName)
{
// Label
Control
Label NewLabel = new Label();
NewLabel.Width = (panel1.Width / 3)
+ 5; // Space little less than 2/3
NewLabel.Height = BoxHeight;
NewLabel.Left = 0; // Start at the left edge of the panel1
NewLabel.Top = TopValue;
panel1.Controls.Add(NewLabel);
NewLabel.TextAlign =
ContentAlignment.MiddleRight;
NewLabel.Text = LabelName;
}
private
void SCRBar_Scroll(object
sender, ScrollEventArgs e)
{
panel1.Top = -SCRBar.Value;
}
private
void FieldList_SizeChanged(object sender, EventArgs
e)
{
ScrollSet();
}
private
void ScrollSet()
{
if
(panel1.Height > this.Height)
{
SCRBar.Enabled = true;
SCRBar.Maximum = panel1.Height
- this.Height;
}
else
{
SCRBar.Enabled = false;
}
panel1.Top = 0; // Set container's 'top' value
}
public List<string>
GetValues()
{
List<string> strValues = new
List<string>();
foreach
(Control BoxControlText in panel1.Controls)
{
if
(BoxControlText is TextBox || BoxControlText is ComboBox)
{
strValues.Add(BoxControlText.Text);
}
}
return
strValues;
}
public void SetValues(List<string> BoxValues)
{
int ii = 0;
foreach
(Control BoxControlText in panel1.Controls)
{
if
(BoxControlText is TextBox || BoxControlText is ComboBox)
{
BoxControlText.Text =
BoxValues[ii];
ii++;
}
}
}
}
}
Above code is the entire code for the control. I am pretty sure this can be done some easier ways, but the code is doing exactly what I need. If you do come up with some more shortcuts for it, please let me know.
'File.Exists(FieldFilePath)' One of my best friends in coding when it comes to check a file or a folder.
panel1.Width = (this.Width - 10) - SCRBar.Width; Sometimes I set the width of some of the controls during runtime. It's good practice to make things more organize on your application. for (ii = 0; ii < SkipFirstLines; ii++) Here is the code when we skip the first lines (optional). The reason I decided to have header lines in Field List file to put some reminders or warnings. Sometimes people open text files and screw around with them, it's good thing to let them now not to touch to some of them.
ControlCount = ControlCount + (BoxHeight + 2); This line is the main line which the height of the container calculated. Also it sets where the next control (Label, textbox and/or combo box) will be located from top (of the container).
ControlBoxName = LabelText.Replace(' ','_'); When I name the controls, I made sure there are no spaces between words. I also added "cbo" and/or "txt" start of the names to identify them.
panel1.Controls.Add(NewTextBox); Each control has "add" method, so all we have to do is to add the controls into wherever we want... in this case into container control. Just in case you ask "Why into the container. I use the container group everything and actually move it up and down with the scrollbar if items get more than fits in the control itself (Check private void ScrollSet() method).
I used List<string> a lot in this code. I also used "@" as my separator for the Drop Down menu items, and a "hidden listbox" to keep the "header text" during settings. Remember, those things can be done with many ways. You don't have to use separators, you can use other methods such as lines, or use a database to keep y our drop down information and other field information. instead of a "hidden listbox", you can write your own array class etc. I went shortcut, the tools available for me instead of writing more lines of code. A habit from VB world. Pros will roll their eyes for this code... which I want to know how would they do :)