0

I'm trying to update a the text inside a label in a Windows Forms launched from a Console Application, as an example I've created this code.

    static void Main(string[] args)
    {
        Form form = new Form();
        Label label = new Label();

        label.Text = "hi";
        form.Controls.Add(label);
        form.ShowDialog();

        Thread.Sleep(2000);

        label.Text = "bye";
        label.Invalidate();
        label.Update();
        //Refresh Doesn't work either
        //_BuyLabel.Refresh();
        Application.DoEvents();
    }

I've done my research but my knowledge of Windows Forms is quite limited, the libraries for this are already included and are not a problem.

What else do I need to do to update the text or any other Control feature?

Aryan Firouzian
  • 1,940
  • 5
  • 27
  • 41
Xavi
  • 124
  • 2
  • 9

4 Answers4

0

Updated:


You need to create a thread that runs the form and allows updates to labels or other form methods. Create a class with a form in it.

Update your code to follow the below similar example . The main gist is the thread creation and the DoWork() method. You have to run the form in its own thread otherwise it will get blocked. Create your MyForm class that inherits from :Form and add a updateLabel function that you can call in the DoWork method after creating the thread.

The error is you are getting is from Application.SetCompatibleTextRenderingDefault(false); . You can take this out.


static void Main(string[] args)
{
        Console.WriteLine("Press return to launch the form.");
        Console.ReadLine();

        Application.EnableVisualStyles();


        MyForm testForm = new MyForm();

        System.Threading.Thread worker = new System.Threading.Thread(DoWork);
        worker.Start(testForm);

        Application.Run(testForm);
    }

    private static void DoWork(object formObject)
    {
        MyForm form = formObject as MyForm;

        for (int i=0; i<=30; ++i)
        {
            form.UpdateLabel(i.ToString());
            System.Threading.Thread.Sleep(1000);
        }
    }
SoftwareCarpenter
  • 3,835
  • 3
  • 25
  • 37
  • Got a System.InvalidOperationException pm UpdateTextBox method. Currently trying to fix it, let me know if im missing something else. Thanks for your help. – Xavi Feb 14 '18 at 03:23
  • When you step the code where is the error occurring? You need to create the UpdateTextBox(String x) method in your class in order for it to work. – SoftwareCarpenter Feb 14 '18 at 12:26
  • That's what I did in first place, the exception is in the method, right at: Form.Text = text; – Xavi Feb 14 '18 at 18:23
  • I think it has to do with making the calls thread safety, like in this link provided by [VS](https://learn.microsoft.com/en-us/dotnet/framework/winforms/controls/how-to-make-thread-safe-calls-to-windows-forms-controls) I'm trying to use backgroundworker – Xavi Feb 14 '18 at 19:59
  • I was able to run the code in linqpad with no errors. Where are you calling Form.text from? It should be inside of your form class and within the method you supply to the dowork thread . Ie myformclass.updateText() .... – SoftwareCarpenter Feb 14 '18 at 21:28
  • It is just like doing what is described in this post. Updating a progress bar in a windows form . You need a separate thread. https://stackoverflow.com/questions/12126889/how-to-use-winforms-progress-bar hope this helps – SoftwareCarpenter Feb 14 '18 at 21:33
0

Try this:

class Program
{
    private static Form form = new Form();
    private static Label label = new Label();

    static void Main(string[] args)
    {
        label.Text = "hi";
        form.Controls.Add(label);

        form.Load += Form_Load; // Add handle to load event of form

        form.ShowDialog();
        Application.DoEvents();

    }

    private async static void Form_Load(object sender, EventArgs e)
    {
        await Task.Run(() =>             // Run async Task for change label.Text
        {
            Thread.Sleep(2000);
            if (label.InvokeRequired)
            {
                label.Invoke(new Action(() =>
                {
                    label.Text = "bye";
                    label.Invalidate();
                    label.Update();
                }));
            }
        });
    }
}

I run this on my pc, and work.

henoc salinas
  • 1,044
  • 1
  • 9
  • 20
  • It worked for me so far, however, the whole form is unresponsive, I think it must be done on another thread maybe? – Xavi Feb 14 '18 at 03:28
  • Throws InvalidOperationException on label.Text = "bye". It's the same issue as the first question I guess, making some tests on it. – Xavi Feb 14 '18 at 03:48
  • ok, Im going to modify again the code on answer, try add a handle load event, a run asynk task in this. – henoc salinas Feb 14 '18 at 04:09
  • please view this [link](https://stackoverflow.com/help/someone-answers) – henoc salinas Feb 14 '18 at 18:54
  • Technically, Task.Run is not async. It creates a new thread in-order to do the work, making it concurrent. It is probably a bad idea to be creating a thread for such little work. You risk overwhelming the thread pool. – David Price May 19 '21 at 14:15
0

If all you want is customization on startup, this is actually really simple; just like with any other object you want to customize, give it a constructor that accepts any arguments you want to use to customize the class behaviour. Like, in your case, the label text.

There is no need for threading or communication here. Setting that label from an external source is completely unnecessary. Just design the form class in advance, with the label already on it, and give it a custom constructor which accepts the string to put on that label.

static void Main(string[] args)
{
    MyForm form = new MyForm("hi");
    form.ShowDialog();
}

And in the MyForm class itself:

public MyForm(string labelText)
{
    // Generated code.
    InitializeComponent();
    // Set label text
    this.lblInfo.Text = labelText;
}

By the way... I'm not sure if you're clear on what a "console app" really is. Any program can be started from command prompt, and it's perfectly possible to give a Windows app the static void Main(String[] args) constructor to make it accept command line parameters, and, in fact, also like any other application, you can change the Main function's return type to int to make it return an exit code after it finished running. There is usually little use for a console app to show forms, though; that generally defeats the purpose of a console app.

Nyerguds
  • 5,360
  • 1
  • 31
  • 63
  • I'm using a console app as an example because I plan to attach my code on a third party software, the API they provide is limited but I can use Windows Forms, it's not like using Visual Studio and setting a Windows Forms Project, I was able to get some windows working in it but in this case it did not update, and I've been trying to know why. Will try your solution, thanks for your help. – Xavi Feb 14 '18 at 18:34
0

Just Add public function to change the existing label in the form:

public void changeLabelText(string text)
{
   this.label1.Text=text; // label1 is the label that you want to change the text
}

And from the main function you call this function after creating form object

form.changeLabelText("text");

For this you need to create new form Example MainForm

Elbek
  • 616
  • 1
  • 4
  • 15
  • Hello Elbek, this is not working, also it doesn't deal with the whole form becoming unresponsive. – Xavi Feb 14 '18 at 19:37