|
I am a newbie in .net.
I have a windows form with a few controls on it. In the same namespace, I have a class file in which i am trying to access a label in the form to update its text, but the intellisense does not bring up the form controls when i type the form name in the class file.
I also changed the access modifier of the label from private to public, but that did not help.
How do i access the form controls in the class file? any help is appreciated.
|
| needtechhelp Tuesday, June 05, 2007 3:22 PM |
You seem to be confusing something... In this situation you could use a ParameterizedThreadStart and pass the instance...
Code Snippet
private void button_Click(....) { Thread titleThread = new Thread( new ParameterizedThreadStart(t1.PopulateIndTerms)); titleThread.Start( this ); // this is a reference to the Form1 instance }
Code Snippet
public void PopulateIndTerms(object data) { Form1 form1 = data as Form1; form1.BlahBlahText = "hello world"; } (Another approach could be TermThread t1 = new TermThread( "title", this); // pass in the reference to this form, and then store this reference in the constructor... And access it in the PopulateIndTerms ) |
| timvw Tuesday, June 05, 2007 4:38 PM |
OK, I read up the article on MSDN: "How to: Make Thread-Safe Calls to Windows Forms Controls" (http://msdn2.microsoft.com/en-us/library/ms171728.aspx).
and as per that, I defined the delegate & created the SetText method in the form1 class as follows:
delegate void SetTextCallback(string text); public void SetText(string text) { if (this.lblTitleStartTime.InvokeRequired) { SetTextCallback d = new SetTextCallback(SetText); this.Invoke(d, new object[] { text }); } else { this.lblTitleStartTime.Text = text; } }
& in the TermThread class file, changed the PopulateIndTerms as follows:
public void PopulateIndTerms(object data) { Form1 form1 = data as Form1; //form1.BlahBlahText = "hello world"; form1.SetText("hello world"); }
That made it work. Thanks for all your help.
|
| needtechhelp Tuesday, June 05, 2007 6:48 PM |
- Are you working witn an instance of the form class? Or are you trying to access a (non-existing) static property (eg: Form.SomeProperty) - In general i would recommend against making control visible to the outside.. It's a source of many problems as soon as you try to manipulate them from a thread that is not the UI-thread... - Instead you could define a public property (or method) as following:
Code Snippet
public string BlahBlahText { get { return this.someLabel.Text; } set { if (this.InvokeRequired) { // thread marshalling is required new MethodInvoker(delegate { BlahBlahText = value; }).Invoke(); } else { // we're on the right thread, do the actual work this.someLabel.Text = value; } } } This way you don't have to care about the thread-related problems to this control, you can easily replace the label (and directly setting it's text property) with another implementation (eg: databindd to a RichTextBox) |
| timvw Tuesday, June 05, 2007 3:54 PM |
Yes, I am working with the instance of a form class that visual studio created for me. Here's what I am doing:
- on click of a button in the form, i am creating multiple threads as follows (in form1.cs): private void btnIndterms_Click(object sender, EventArgs e) { TermThread t1 = new TermThread("title"); Thread titleThread = new Thread(new ThreadStart(t1.PopulateIndTerms)); TermThread t2 = new TermThread("lastname"); Thread lnameThread = new Thread(new ThreadStart(t2.PopulateIndTerms)); titleThread.Start(); lnameThread.Start(); }
- where TermThread is the name of my class & is in a separate class file called TermThread.cs, but in the same namespace. - in the PopulateIndTerms method, I want to update the text in a label of form1, but i can't seem to do it.
hope this helps.
|
| needtechhelp Tuesday, June 05, 2007 4:14 PM |
You seem to be confusing something... In this situation you could use a ParameterizedThreadStart and pass the instance...
Code Snippet
private void button_Click(....) { Thread titleThread = new Thread( new ParameterizedThreadStart(t1.PopulateIndTerms)); titleThread.Start( this ); // this is a reference to the Form1 instance }
Code Snippet
public void PopulateIndTerms(object data) { Form1 form1 = data as Form1; form1.BlahBlahText = "hello world"; } (Another approach could be TermThread t1 = new TermThread( "title", this); // pass in the reference to this form, and then store this reference in the constructor... And access it in the PopulateIndTerms ) |
| timvw Tuesday, June 05, 2007 4:38 PM |
thanks for your help.
However, when i use either of the approaches that you mentioned above, i get an InvalidOperationException error at the line where i am setting the text:
Cross-thread operation not valid: Control 'lblLastNameStartTime' accessed from a thread other than the thread it was created on.
|
| needtechhelp Tuesday, June 05, 2007 6:13 PM |
Show us your code.. (As i already showed in my first example, you'll have to check the InvokeRequired property, and if it's true, do some thread-marshalling)
|
| timvw Tuesday, June 05, 2007 6:38 PM |
OK, I read up the article on MSDN: "How to: Make Thread-Safe Calls to Windows Forms Controls" (http://msdn2.microsoft.com/en-us/library/ms171728.aspx).
and as per that, I defined the delegate & created the SetText method in the form1 class as follows:
delegate void SetTextCallback(string text); public void SetText(string text) { if (this.lblTitleStartTime.InvokeRequired) { SetTextCallback d = new SetTextCallback(SetText); this.Invoke(d, new object[] { text }); } else { this.lblTitleStartTime.Text = text; } }
& in the TermThread class file, changed the PopulateIndTerms as follows:
public void PopulateIndTerms(object data) { Form1 form1 = data as Form1; //form1.BlahBlahText = "hello world"; form1.SetText("hello world"); }
That made it work. Thanks for all your help.
|
| needtechhelp Tuesday, June 05, 2007 6:48 PM |