locked
How can I create a label in run time? RRS feed

  • Question

  • I have a project where I am wanting to use labels (for each msg log in the debug list) to make a bar graph during run time. The problem is, I am unable to create a label during runtime! Every time I get a particular Error log ID that bar Will go up +1. I have tons and tons of experience programming in C#, but I rarely use the GUI tools to get work done. How can I create labels/textbox's in run time in this code? namespace DebugViewer { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void openFileDialog1_FileOk(object sender, CancelEventArgs e) { txtPathToFile.Text = openFileDialog1.FileName; } private void button1_Click(object sender, EventArgs e) { openFileDialog1.ShowDialog(); } private void btnViewLog_Click(object sender, EventArgs e) { // backgroundWorker1.RunWorkerAsync(); } private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) { String curLine = ""; //**************reading log msg files************************* FileStream trstrm = new FileStream(openFileDialog1.FileName, FileMode.Open); TextReader tr = new StreamReader(trstrm); //**************creation of database variables********************** SQLiteConnection sqlite_conn; SQLiteCommand sqlite_cmd; SQLiteDataReader sqlite_datareader; // create a new database connection: sqlite_conn = new SQLiteConnection("Data Source=database.db;Version=3;New=True;Compress=True;"); // open the connection: sqlite_conn.Open(); // create a new SQL command: sqlite_cmd = sqlite_conn.CreateCommand(); /* Msg Log structure 1. Error ID type 2. FNC or blank 3. Plex Object Name 4. Plex Object ID 5. 10 or 0 6. Plex Object ID or 0 7. another unique error ID type 8. Error/Information/Warning 9. Date "9/25/2008" 10. Time "10:41 AM" 11. Actual Error Msg */ sqlite_cmd.CommandText = "drop TABLE msgLog;"; sqlite_cmd.ExecuteNonQuery(); // Let the SQLiteCommand object know our SQL-Query: sqlite_cmd.CommandText = "CREATE TABLE msgLog (logid integer primary key, errorId integer, plexObjectName varchar(200), errorMsg varchar(200));"; sqlite_cmd.ExecuteNonQuery(); //*************Insert values from MSG file into Database*********** int logid=0; while ((curLine = tr.ReadLine()) != null)//read textreader { char[] TokenChars = { ',' }; string[] splitedValues = curLine.Split(TokenChars); sqlite_cmd.CommandText = "INSERT INTO msgLog (logid, errorId, plexObjectName, errorMsg) VALUES (@LOGID, @ERRORID, @PONAME, @MSGDETAILS);"; sqlite_cmd.Parameters.AddWithValue("@LOGID", logid); sqlite_cmd.Parameters.AddWithValue("@ERRORID", splitedValues[0]); sqlite_cmd.Parameters.AddWithValue("@PONAME", splitedValues[1]); sqlite_cmd.Parameters.AddWithValue("@MSGDETAILS", splitedValues[10]); sqlite_cmd.ExecuteNonQuery(); logid++; } //************************** //Create a label for each Error msg in my log here sqlite_conn.Close(); } } }
    Friday, September 26, 2008 2:53 PM

Answers

  • 1. Oh my word.  Please, PLEASE, format your code better when you post.  Are you trying to kill us?

    2. Use the GUI tools to get things done.  You'll save yourself time and headache.

    3. You can't create a label in a BackgroundWorker_DoWork event handler.  You'll get a cross-thread exception at runtime, because this method runs on a separate thread as the UI. 
    Set your BackgroundWorker.WorkerReportsProgress value to true. 
    Create a handler for BackgroundWorker.ProgressChanged, and write your label creation code in there.  ("Label l = new Label()" etc.) 
    Call the BackgroundWorker's ReportProgress method within the "DoWork" method, and send in the string you want to put on the label as the userState object.
    Use e.UserState in your ProgressChanged event handler as the text for your label.
    David Morton - http://blog.davemorton.net/
    • Marked as answer by jack 321 Tuesday, September 30, 2008 5:43 AM
    Friday, September 26, 2008 3:17 PM
  • 1//**************************   
    2//Create a label for each Error msg in my log here   
    3   
    4BeginInvoke( new MethodInvoker ( () => { 
    5foreach (string error in errors) {   
    6    Label lbl = new Label();   
    7    lbl.Text = error;   
    8    flowLayoutPanel1.Controls.Add(lbl);   
    9}   
    10})); 
    11sqlite_conn.Close();  


    (Be aware that I didn't check this code against the compiler. I may have missed some curly braces or parenthesis in the middle of that BeginInvoke mess)

    Creating a Control like in the Designer is easy, there's no voodoo to it. The only tricky part is knowing where to place it.

    My idea here is to use a FlowLayoutPanel where you put your labels. So, in the Designer, add a FlowLayoutPanel to your Form, set its AutoSize property to true, and give it enough room to expand (don't put other Controls too close). Oh, and set its FlowDirection property to UpDown (I don't remember how it's called, but look for a property which makes the components flow up down instead of the default left to right).

    If you're not happy with how the labels look like, create one in the Designer, then look at the MyForm.Designer.cs file, to see how it's initialized. Maybe you want to change the Font. It's non trivial, the easier/faster is to do it in the Designer, then copy and paste it into your code.

    If you want to clear the error messages before adding the latest ones, add flowLayoutPanel1.Controls.Clear() before line 4.

    By the way, you should protect the statement in line 10, in a finally block, or with a using statement. Unless you removed it here to make your code more readable?

    I hope my code is clear. Do you have any more questions? Please ask.



    PS:
    Armastevs said:

    I have tons and tons of experience programming in C#, but I rarely use the GUI tools to get work done.

    I'm not impressed


    if a problem looks too big, break it into smaller objects
    • Edited by M0nkeyMaster Friday, September 26, 2008 3:35 PM didn't notice the BackgroundWorker.DoWork
    • Marked as answer by jack 321 Tuesday, September 30, 2008 5:43 AM
    Friday, September 26, 2008 3:32 PM

All replies

  • 1. Oh my word.  Please, PLEASE, format your code better when you post.  Are you trying to kill us?

    2. Use the GUI tools to get things done.  You'll save yourself time and headache.

    3. You can't create a label in a BackgroundWorker_DoWork event handler.  You'll get a cross-thread exception at runtime, because this method runs on a separate thread as the UI. 
    Set your BackgroundWorker.WorkerReportsProgress value to true. 
    Create a handler for BackgroundWorker.ProgressChanged, and write your label creation code in there.  ("Label l = new Label()" etc.) 
    Call the BackgroundWorker's ReportProgress method within the "DoWork" method, and send in the string you want to put on the label as the userState object.
    Use e.UserState in your ProgressChanged event handler as the text for your label.
    David Morton - http://blog.davemorton.net/
    • Marked as answer by jack 321 Tuesday, September 30, 2008 5:43 AM
    Friday, September 26, 2008 3:17 PM
  • 1//**************************   
    2//Create a label for each Error msg in my log here   
    3   
    4BeginInvoke( new MethodInvoker ( () => { 
    5foreach (string error in errors) {   
    6    Label lbl = new Label();   
    7    lbl.Text = error;   
    8    flowLayoutPanel1.Controls.Add(lbl);   
    9}   
    10})); 
    11sqlite_conn.Close();  


    (Be aware that I didn't check this code against the compiler. I may have missed some curly braces or parenthesis in the middle of that BeginInvoke mess)

    Creating a Control like in the Designer is easy, there's no voodoo to it. The only tricky part is knowing where to place it.

    My idea here is to use a FlowLayoutPanel where you put your labels. So, in the Designer, add a FlowLayoutPanel to your Form, set its AutoSize property to true, and give it enough room to expand (don't put other Controls too close). Oh, and set its FlowDirection property to UpDown (I don't remember how it's called, but look for a property which makes the components flow up down instead of the default left to right).

    If you're not happy with how the labels look like, create one in the Designer, then look at the MyForm.Designer.cs file, to see how it's initialized. Maybe you want to change the Font. It's non trivial, the easier/faster is to do it in the Designer, then copy and paste it into your code.

    If you want to clear the error messages before adding the latest ones, add flowLayoutPanel1.Controls.Clear() before line 4.

    By the way, you should protect the statement in line 10, in a finally block, or with a using statement. Unless you removed it here to make your code more readable?

    I hope my code is clear. Do you have any more questions? Please ask.



    PS:
    Armastevs said:

    I have tons and tons of experience programming in C#, but I rarely use the GUI tools to get work done.

    I'm not impressed


    if a problem looks too big, break it into smaller objects
    • Edited by M0nkeyMaster Friday, September 26, 2008 3:35 PM didn't notice the BackgroundWorker.DoWork
    • Marked as answer by jack 321 Tuesday, September 30, 2008 5:43 AM
    Friday, September 26, 2008 3:32 PM