I'm creating a WinForm application in C# and one of its functions is displaying text in text boxes. I'm coding the logic for querying a database in a separate class and am unable to access the text box element in the class I'm creating (I'm getting a "name" does not exist in the current context error). Do I put all of my form logic into my Form1.cs file?
You should try to keep your display logic separate from the rest of the application - the simplest thing to do is have the form class handle getting/setting form values. This means your data access component will query the database and the form will have to map the output to something that can be displayed e.g.
public class Form1 : Form
{
public DataAccess Db { get; set; }
public void UpdateSomething()
{
this.textbox.Text = this.Db.GetSomeDatabaseValue();
}
}
No keep Business logical apart from UI logic. You should raise an event in the Business class and catch it in the UI form. From there display it.
If they are not try setting the modifiers in properties to public or internal.
Edit- edited to fit answer format
If you want to access the TextBox in another class change the access modifier as
public or Internal (If it is in the same assembly)
.
Default it will be private
Better you can pass the value to the business logic layer.Not the entire control,would not be good always.
B.I is to do all the business so the value of text box is enough.
Have you looked at the backgroundworker? With this, you can run things asynchronously when you click a button on your form. All of your updating things on your form would be done on your form itself. Your other code (that you were having trouble accessing Form1 from) would 'report progress.' When progress is reported, you can send any object that you want to Form1 and then in an event handler on the form you can take information from that object and update the view. You would use this, for example, to update a progress bar while keeping the UI responsive.
We are currently doing an application with a MVP pattern in winforms. We are using the bindings in winforms so the UI will update when the data does. Our forms use BindingSources and BindingLists. We bind the main BindingSource to our presenter class.
Example of Form codebehind
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using SomeNameSpace.Utilities.UI;
using SomeNameSpace.Utilities.Validation;
namespace Management.UI
{
public partial class ManualControl : UserControl, IManualRaffleView
{
private ManualPresenter _presenter;
public ManualControl()
{
InitializeComponent();
}
[Browsable(false)]
public ManualPresenter Presenter
{
get
{
return _presenter;
}
set
{
_presenter = value;
if(_presenter != null)
{
_manualPresenterBindingSource.DataSource = _presenter;
_ListBindingSource.DataSource = _presenter;
_ListBindingSource.DataMember = "Something";
_KindListBindingSource.DataSource = _presenter;
_KindListBindingSource.DataMember = "SomethingElse";
_presenter.CloseView += new Action(CloseMe);
_presenter.VerifyingCancel += new Func<bool>(VerifyingCancel);
_presenter.Showing += new Action(ShowMe);
_presenter.Synchronizer = this;
}
}
}
void CloseMe()
{
this.Enabled = false;
}
private void ManualRaffleForm_FormClosing(object sender, FormClosingEventArgs e)
{
e.Cancel = false;
}
private void ShowMe()
{
this.Enabled = true;
}
bool VerifyingCancel()
{
return MessageBox.Show("Cancel?", Notifier.ApplicationName,
MessageBoxButtons.YesNo, MessageBoxIcon.Question,
MessageBoxDefaultButton.Button2) == DialogResult.Yes;
}
private void _cancelButton_Click(object sender, EventArgs e)
{
Presenter.HandleCancel();
}
private void _initiateButton_Click(object sender, EventArgs e)
{
Presenter.HandleInitiate();
}
private void _saveButton_Click(object sender, EventArgs e)
{
if(Presenter.Error == true.ToString())
Presenter.HandleDone();
else
_manualPresenterBindingSource.ResetBindings(false);
}
}
}
Then our Presenter implements INotifyPropertyChanged and may look something like this
namespace SomeCompany.UI
{
public class ManualPresenter : INotifyPropertyChanged, IDataErrorInfo
{
#region Fields
//fields
#endregion Fields
public string SomeFormField
{ get{ return _someFormField;}
set{
if(_someFormField != value)
{
_someFormField = value;
//Update Model if Needed
_model.SomeFormField = _someFormField;
NotifyCHanged("SomeFormField");
}
}
}
The form text boxes will bind to the properties in the presenter and any listboxes or combo boxes will bind to BindingLists.
We then use Linq to Sql for our models. There is very little logic in the Forms. Mostly just a little that is necessary for validation.
Related
So, I'm currently working on a game library app, where you can add and organize games that are a part of your game library. So far I have three textboxes (one for game title, developer, and publisher), one checklistbox (to select which platform or system the game is on), three buttons ("Save Changes", "Add", and "Delete"), and finally a listview where the title of the game will be displayed whenever the user enters in the information and clicks the "Add" button. I was able to get it to work with no problems using the Form1.csclass, but figured it'd be best to organize the code using classes, which I've NEVER done with Windows Forms before (so I'm kinda a noob at this). For consistency reasons for this post, I made a saveAddDelete.csclass that has all my code for the "Save", "Add", and "Delete" buttons, which I transferred over from Form1.cs. I then call the saveAddDelete.csclass in Form1.csunder the designated button click events. There are no errors, but when I run the program, I enter in the information and click on the buttons, but they do nothing. So I think I'm either missing code or misunderstanding how classes work in Windows Forms. Here's the code below, and if anyone has any helpful feedback that would help me, I'd greatly appreciate it.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace GameLibrary
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public List<Library> Game = new List<Library>();
public Library lib = new Library();
public void saveBttn_Click(object sender, EventArgs e)
{
saveAddDelete save = new saveAddDelete();
save.Save();
}
private void button1_Click(object sender, EventArgs e)//Add Button
{
saveAddDelete add = new saveAddDelete();
add.Add();
}
private void deleteBtnClick_Click(object sender, EventArgs e)
{
saveAddDelete delete = new saveAddDelete();
delete.Delete();
}
public class Library
{
public string gametitle
{
get;
set;
}
public string developer
{
get;
set;
}
public string publisher
{
get;
set;
}
public string platform
{
get;
set;
}
}
class saveAddDelete
{
Form1 f = new Form1();
public void Save()
{
if(f.gameList.SelectedItems.Count == 1)
{
f.Game[f.gameList.SelectedItems[0].Index].gametitle = f.titleText.Text;
f.Game[f.gameList.SelectedItems[0].Index].developer = f.developerText.Text;
f.Game[f.gameList.SelectedItems[0].Index].publisher = f.publisherText.Text;
f.Game[f.gameList.SelectedItems[0].Index].platform = f.platformCheckBox.CheckedItems.ToString();
}
}
public void Add()
{
f.lib.gametitle = f.titleText.Text;
f.lib.developer = f.developerText.Text;
f.lib.publisher = f.publisherText.Text;
f.lib.platform = f.platformCheckBox.CheckedItems.ToString();
f.Game.Add(f.lib);
f.gameList.Items.Add(f.lib.gametitle);
f.titleText.Clear();
f.developerText.Clear();
f.publisherText.Clear();
foreach(int i in f.platformCheckBox.CheckedIndices)
{
f.platformCheckBox.SetItemCheckState(i, CheckState.Unchecked);
}
}
public void Delete()
{
Remove();
f.titleText.Clear();
f.developerText.Clear();
f.publisherText.Clear();
foreach (int i in f.platformCheckBox.CheckedIndices)
{
f.platformCheckBox.SetItemCheckState(i, CheckState.Unchecked);
}
}
void Remove()
{
try
{
f.gameList.Items.Remove(f.gameList.SelectedItems[0]);
f.Game.RemoveAt(f.gameList.SelectedItems[0].Index);
}
catch { }
}
}
Your helper class does not have reference to real form clicks are performed on (and hence do not get any values from the form).
One option - pass Form1 to each call instead of new'ing up Form1 in saveAndDelete class:
class saveAddDelete
{
// Form1 f = new Form1(); - delete that line
public void Save(Form1 f) {....} // pass Form1
and in each event handler pass this:
public void saveBttn_Click(object sender, EventArgs e)
{
saveAddDelete save = new saveAddDelete(this);
save.Save();
}
Note that you may consider using static methods for Save depending on your goals.
In your Form1 code, you create a new child object of type SaveAddDelete, but when you use the methods you created, you aren't passing any data into them. Instead, you are creating a new (empty) instance of Form1, which doesn't have any data to save or delete, and if you make any modifications to that new Form1, the original version of Form1 is not able to see those changes. You wind up with 2 different Form1's, neither of which know anything about the other one.
If you want to do it this way, you will need to pass a reference to the existing Form1 to the SaveAddDelete class:
public void saveBttn_Click(object sender, EventArgs e)
{
saveAddDelete save = new saveAddDelete();
save.Save(this);
}
and your SaveAddDelete methods will have to be expecting to receive an object of type Form1:
public void Save(Form1 f)
{
if(f.gameList.SelectedItems.Count == 1)
{
f.Game[f.gameList.SelectedItems[0].Index].gametitle = f.titleText.Text;
f.Game[f.gameList.SelectedItems[0].Index].developer = f.developerText.Text;
f.Game[f.gameList.SelectedItems[0].Index].publisher = f.publisherText.Text;
f.Game[f.gameList.SelectedItems[0].Index].platform = f.platformCheckBox.CheckedItems.ToString();
}
}
Notice that in the top sample, I pass "this" to the method, which is C# code for "whatever class is calling the code." In this case, "this" refers to your existing Form1 object. In the bottom sample, notice that the save method expects a Form1 object named "f" as a parameter. It does not create a new Form1 - it uses the one you pass to it.
For this example, I would actually just leave all of those methods in your Form1 class, since they are all related to the controls in Form1. New classes are generally used to model real-world objects - not to break out various pieces of code related to an existing class. Your "Library" class is a correct use of a separate class, since each instance of it represents a different game, and you have more than one of them that you need to keep track of separately (although I would call the class "Game" instead of "Library", since each instance of the class represents a single game, whereas the word library implies a collection of games.)
I'm learning about databinding, I have a Class with one property, then I have another class with a combobox and 2 values "1 and 2", I've created an array object of my class with the property, so when combobox has 1 my textbox will give it a value to class[0].property, instead if I have 2 this happens class[1].property here is the code so you will understand better:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WindowsFormsApplication1
{
struct Class1
{
public string pollo { get; set; }
}
}
My second class:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
Class1[] prova = new Class1[2];
int a;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
a = Convert.ToInt32(comboBox1.SelectedItem) - 1;
prova[a].pollo = textBox1.Text;
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
a = Convert.ToInt32(comboBox1.SelectedItem) - 1;
textBox1.DataBindings.Add("Text", prova[a], "pollo", false, DataSourceUpdateMode.OnPropertyChanged);
textBox1.DataBindings.Clear();
}
private void Form1_Load(object sender, EventArgs e)
{
comboBox1.SelectedIndex = 0;
}
}
}
All works fine, but this is a one way databinding in fact I have to set the property with the click button and in this case there is no such difference between:
textBox1.DataBindings.Add("Text", prova[a], "pollo", false, DataSourceUpdateMode.OnPropertyChanged);
and
textBox1 = prova[a];
So why use a databinding? I mean how can I make it two ways so that automatically set my property?
Thanks
You have some problems in your code, preventing the binding from working correctly, and so obscuring the usefulness.
First, to be clear: the binding that is being set is between the currently selected Class1 object and the Text property of the TextBox. You are using the ComboBox to change the currently selected object to bind the TextBox to. I'm assuming you're aware of this, but I want to make sure.
Now, as far as the problems in the code go…
The most serious problem is that your data type Class1 is being declared as a struct, rather than as a class. The struct type is a value type, meaning whenever code needs an object reference, a copy of the value is boxed (stored in an instance of object). It's very important to understand that this boxed value is a copy. It is completely disconnected from the value you've stored in your array, so even if the binding were successfully set, changes to the object would not be reflected elsewhere in the code where you retrieve the object value from the array.
Almost as serious is that you clear the binding immediately after setting it. This completely negates the point of data binding, which is to allow the framework to automatically update property values based on changes in another object. So yes, in your code example there is literally no difference whatsoever between the set-binding-then-clear-binding operation and simply setting the property directly.
Either of these two problems is sufficient to prevent data binding from working in a useful way. But there is also a third problem…
Your Class1 type does not implement a property changed event. In Winforms, you can implement either an event with the name polloChanged (i.e. the property name, followed by the word Changed, spelled and capitalized exactly like that), or by implementing the INotifyPropertyChanged interface. Without either of these mechanisms, two-way data binding cannot work, because the framework has no way to know when the value of the property has changed. (Ironically, what does work is the target-to-source binding…that is, because the TextBox class does implement the TextChanged event, the data binding is able to set the source property when the target property changes. But it doesn't go the other way).
Here is a version of your code that takes full advantage of data binding, implementing Class1 correctly (as an actual class, and with the necessary polloChanged event), configuring the binding correctly, and binding the object's pollo property to a Label so that it's clear the object's pollo property is being updated:
class Class1
{
private string _pollo = "";
public string pollo
{
get { return _pollo; }
set
{
_pollo = value;
Raise(polloChanged, this);
}
}
private static void Raise(EventHandler handler, object sender)
{
if (handler != null)
{
handler(sender, EventArgs.Empty);
}
}
public event EventHandler polloChanged;
}
public partial class Form1 : Form
{
private Class1[] _prova =
{
new Class1 { pollo = "<not set 1>" },
new Class1 { pollo = "<not set 2>" }
};
public Form1()
{
InitializeComponent();
comboBox1.SelectedIndex = 0;
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
// Obviously in a more complicated data binding scenario, you might
// want to be more specific about which binding(s) is(are) being
// removed, rather than just clearing everything.
textBox1.DataBindings.Clear();
label1.DataBindings.Clear();
// If the user edits the text in the TextBox, the pollo property
// of the currently-selected object will be immediately updated
textBox1.DataBindings.Add("Text", _prova[comboBox1.SelectedIndex],
"pollo", false, DataSourceUpdateMode.OnPropertyChanged);
// We're never going to change the label1.Text property directly,
// so the binding doesn't ever need to update the source property.
label1.DataBindings.Add("Text", _prova[comboBox1.SelectedIndex],
"pollo", false, DataSourceUpdateMode.Never);
}
}
I assume you can infer the necessary textBox1, comboBox1, and label1 controls in the form, rather than having me post all the Designer code.
Finally, in case you prefer the INotifyPropertyChanged approach, here's what your Class1 would look like using that technique:
class Class1 : INotifyPropertyChanged
{
private string _pollo = "";
public string pollo
{
get { return _pollo; }
set
{
_pollo = value;
OnPropertyChanged();
}
}
private void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
I have written a user control, MenuItem, which inherits from a Form Label.
I have a backgroundworker thread whose IsBusy property is exposed through a property in the MainForm as IsBackgroundBusy.
How do I read this property from the MenuItem usercontrol? I am currently using Application.UseWaitCursor and I set that in the backgroundworker and it works perfectly, however I do not want the cursor to change. That's why I figured a property that I could set would be much better.
Here is the code in my MainForm:
public partial class MainForm : Form
{
public bool IsBackgroundBusy
{
get
{
return bwRefreshGalleries.IsBusy;
}
}
Here is the code for my usercontrol:
public partial class MenuItem: Label
{
private bool _disableIfBusy = false;
[Description("Change color if Application.UseWaitCursor is True")]
public bool DisableIfBusy
{
get
{
return _disableIfBusy;
}
set
{
_disableIfBusy = value;
}
}
public MenuItem()
{
InitializeComponent();
}
protected override void OnMouseEnter( EventArgs e )
{
if ( Application.UseWaitCursor && _disableIfBusy )
{
this.BackColor = SystemColors.ControlDark;
}
else
{
this.BackColor = SystemColors.Control;
}
base.OnMouseEnter( e );
}
(Note: it's not clear to me whether you have an actual UserControl here or not. The MenuItem class you show inherits Label, not UserControl. You should probably avoid using the term "usercontrol" or "user control" when you are not actually dealing with a UserControl object).
Absent a complete code example, it's hard to know exactly what the right solution here is. However, assuming you are using the BackgroundWorker in a typical fashion, then you simply need for the owner of the control (i.e. the containing Form) to pass the necessary state to the control as it changes. E.g.:
class MenuItem : Label
{
public bool IsParentBusy { get; set; }
}
// I.e. some method where you are handling the BackgroundWorker
void button1_Click(object sender, EventArgs e)
{
// ...some other initialization...
bwRefreshGalleries.RunWorkerCompleted += (sender1, e1) =>
{
menuItem1.IsParentBusy = false;
};
menuItem1.ParentIsBusy = true;
bwRefreshGalleries.RunAsync();
}
If you already have a handler for the RunWorkerCompleted event, then just put the statement to set the IsParentBusy property there instead of adding another handler.
Then instead of using the Application.UseWaitCursor property, you can just look at the IsParentBusy property.
There are other mechanisms you could use; I do agree with the general sentiment that the MenuItem control should not be tied to your specific Form sub-class. If for some reason the above doesn't work in your case, you need to elaborate on your question: provide a good code example and explain exactly why simply having the container of the control manage its state directly doesn't work for you
How to send textbox value to textbox between two forms without Show()/ShowDialog() by button?
I want to textBox will get value without open form.
To access the textbox data you need to use: textBox1.Text
a form is an object so you can define a method that updates the text box value (you can expose the textbox itself with a public accessor)
To pass information from a parent from to a child form you should create a property on the child form for the data it needs to receive and then have the parent form set that property (for example, on button click).
To have a child form send data to a parent form the child form should create a property (it only needs to be a getter) with the data it wants to send to the parent form. It should then create an event (or use an existing Form event) which the parent can subscribe to.
An example:
namespace PassingDataExample
{
public partial class ParentForm : Form
{
public ParentForm()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
ChildForm child = new ChildForm();
child.DataFromParent = "hello world";
child.FormSubmitted += (sender2, arg) =>
{
child.Close();
string dataFromChild = child.DataFromChild;
};
child.Show();
}
}
}
namespace PassingDataExample
{
public partial class ChildForm : Form
{
public ChildForm()
{
InitializeComponent();
}
public string DataFromParent { get; set; }
public string DataFromChild { get; private set; }
public event EventHandler FormSubmitted;
private void button1_Click(object sender, EventArgs e)
{
DataFromChild = "Hi there!";
if (FormSubmitted != null)
FormSubmitted(this, null);
}
}
}
I don't know what exactly you mean by saying "without Show()/ShowDialog()", but that is not relevant anyway or I'll just assume here further that you have both windows open (doesn't matter how you accomplished that).
You would like to avoid much coupling between two forms, especially not implementation details like a textbox etc. You could work with delegates and events to trigger the "sending" of data between your two forms. You can then easily pass event data and your subscribed other form (or any other object as a matter of fact) doesn't know the exact implementation details of your form, it only knows the data it will receive through the delegate (event). I am not going to post all code here, because it is already nicely explained at following URL: http://www.codeproject.com/Articles/17371/Passing-Data-between-Windows-Forms .
Although there are some similar questions I’m having difficulties finding an answer on how to receive data in my form from a class.
I have been trying to read about instantiation and its actually one of the few things that does make sense to me :) but if I were to instantiate my form, would I not have two form objects?
To simplify things, lets say I have a some data in Class1 and I would like to pass a string into a label on Form1. Is it legal to instantiate another form1? When trying to do so it looks like I can then access label1.Text but the label isn’t updating. The only thing I can think of is that the form needs to be redrawn or there is some threading issue that I’m unaware of.
Any insight you could provide would be greatly appreciated.
EDIT: Added some code to help
class Class1
{
public int number { get; set; }
public void Counter()
{
for (int i = 0; i < 10; i++)
{
number = i;
System.Threading.Thread.Sleep(5000);
}
}
}
and the form:
Class1 myClass = new Class1();
public Form1()
{
InitializeComponent();
label1.Text = myClass.number.ToString();
}
NO,
I think your form needs to access a reference to Class1 to use the data available in that, and not the other way around.
VERY seldomly a data class should instanciate a display form to display what it has to offer.
If the class is a data access layer of singleton, the form should reference that class, and not the other way around.
Based on the comments in your original post, here are a few ways to do it:
(this code is based on a Winform app in VS2010, there is 1 form, with a Label named "ValueLabel", a textbox named "NewValueTextBox", and a button.
Also, there is a class "MyClass" that represents the class with the changes that you want to publish.
Here is the code for the class. Note that I implement INotifyPropertyChanged and I have an event. You don't have to implement INotifyPropertyChanged, and I have an event that I raise whenever the property changes.
You should be able to run the form, type something into the textbox, click the button, and see the value of the label change.
public class MyClass: System.ComponentModel.INotifyPropertyChanged
{
public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
public string AValue
{
get
{
return this._AValue;
}
set
{
if (value != this._AValue)
{
this._AValue = value;
this.OnPropertyChanged("AValue");
}
}
}
private string _AValue;
protected virtual void OnPropertyChanged(string propertyName)
{
if(this.PropertyChanged != null)
this.PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
}
}
Example 1: simple databinding between the label and the value:
So this time, we will just bind the label to an instance of your class. We have a textbox and button that you can use to change the value of the property in MyClass. When it changes, the databinding will cause the label to be update automatically:
NOTE: Make sure to hook up Form1_Load as the load event for hte form, and UpdateValueButton_Click as the click handler for the button, or nothing will work!
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private MyClass TheClass;
private void Form1_Load(object sender, EventArgs e)
{
this.TheClass = new MyClass();
this.ValueLabel.DataBindings.Add("Text", this.TheClass, "AValue");
}
private void UpdateValueButton_Click(object sender, EventArgs e)
{
// simulate a modification to the value of the class
this.TheClass.AValue = this.NewValueTextBox.Text;
}
}
Example 2
Now, lets bind the value of class directly to the textbox. We've commented out the code in the button click hander, and we have bound both the textbox and the label to the object value. Now if you just tab away from the textbox, you will see your changes...
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private MyClass TheClass;
private void Form1_Load(object sender, EventArgs e)
{
this.TheClass = new MyClass();
// bind the Text property on the label to the AValue property on the object instance.
this.ValueLabel.DataBindings.Add("Text", this.TheClass, "AValue");
// bind the textbox to the same value...
this.NewValueTextBox.DataBindings.Add("Text", this.TheClass, "AValue");
}
private void UpdateValueButton_Click(object sender, EventArgs e)
{
//// simulate a modification to the value of the class
//this.TheClass.AValue = this.NewValueTextBox.Text;
}
Example 3
In this example, we won't use databinding at all. Instead, we will hook the property change event on MyClass and update manually.
Note, in real life, you might have a more specific event than Property changed -- you might have an AValue changed that is only raised when that property changes.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private MyClass TheClass;
private void Form1_Load(object sender, EventArgs e)
{
this.TheClass = new MyClass();
this.TheClass.PropertyChanged += this.TheClass_PropertyChanged;
}
void TheClass_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "AValue")
this.ValueLabel.Text = this.TheClass.AValue;
}
private void UpdateValueButton_Click(object sender, EventArgs e)
{
// simulate a modification to the value of the class
this.TheClass.AValue = this.NewValueTextBox.Text;
}
}
There's no reason why you can't have multiple instances of a form, but in this case you want to pass the Class1 instance to the form you have. The easiest way is to add a property to Form1 and have that update the label text:
public class Form1 : Form
{
public Class1 Data
{
set
{
this.label.Text = value.LabelText;
}
}
}
Events and delegates are what you want to use here. Since you tagged this as beginner, I will leave the implementation as an exercise :), but here is the general idea:
Declare an event/delegate pair in your data class.
Create a method in your form to bind to the event.
When "something" happens in your data class, fire the event
The form's method will be invoked to handle the event and can update widgets appropriately
Good luck.