I would like to update a form's textbox in winforms with data that is being processed from a class file.
Example:
Class.RunProcess();
Inside of RunProcess I would like to fire an event that will update the textbox with the text that I pass in on the win form.
I know you can do this with events so I don't have to make the textbox public or pass it into the many methods I have, I am just not quite sure how to start.
Edit:
Maybe I am just not clear.
I have a windows form with a text box on it.
I have a button that runs a process.
The process is in a class file outside of the form class.
Inside this process method I would like to be able to update the text box on the main form without having to pass the TextBox as a parameter to all the methods that I will have (I currently have 6 and will be more).
I thought I could subscribe to an event that would allow me to display a message in the text box while the processes ran in my class.
It's probably time to consider:
Databinding your textbox to your class
Model/View/Presenter (MVP)
For #1 (Databinding), you can use the INotifyPropertyChanged interface on your class and raise the event for changed properties.
public class BusinessModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private int _quantity;
public int Quantity
{
get { return _quantity; }
set
{
_quantity = value;
this.OnPropertyChanged("Quantity");
}
}
void OnPropertyChanged(string PropertyName)
{
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(PropertyName));
}
}
}
And in your form, youcan bind the .Text property of the textBox to the object in several ways. Through the UI or in code.
Links:
Bind Better with INotifyPropertyChanged
How to: Implement the INotifyPropertyChanged Interface
Now, if you need to add to text that already exists such as in your example, you can either track the full text in the class or raise events from your class and respond in the form code. Tracking it in the class would be better - you really don't want any logic in the form at all, which brings us back to binding and/or some form of MVP/MVC.
If you're wanting Class.RunProcess to run when an event from an external class is fired then you can do it like this
public delegate void MyDelegate();
public class MyClass
{
public event MyDelegate Myevent;
public void DoSomething()
{
this.Myevent();
}
}
public static class Class
{
public static void RunProcess()
{
txtData.Text += "Message";
}
}
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
MyClass myClass = new MyClass();
myClass.Myevent += Class.RunProcess;
}
}
You could add a parameter to your constructor that is a TextBox and save the reference in the class as a private variable and call that in each method.
Related
This has been asked probably many times, but looking through all the other questions I still was not able to solve my issue. I want to update a Datagridview on a form using an update function on this form. The Update function is called by a subscriber.
Overview:
static class MainClass
{
static void Main()
{
// The Main form is called.
MainForm = new frmMain();
Application.Run(MainForm);
//Application.Run(new frmMain());
}
}
A Delegate
public delegate void Delagate_UpdateDataView();
The subscriber that subscribed to publisher that fires an event every 500 ms.
public class SubscriberFrmMain
{
// Constructor
public SubscriberFrmMain()
{
}
// Subscribe to the Publisher
public void Subscribe(PublisherTimedEvent mUpdateHMIData)
{
//attach listener class method to publisher class delegate object
mUpdateHMIData.TickUpdateHMIData += UpdateHMIData;
}
// The Event, fired when the Publisher raises an event.
private void UpdateHMIData(PublisherTimedEvent mUpdateHMIData,EventArgs e)
// Calling the Update function on the Form MainForm.
{
MainClass.MainForm.Process_UpdateDataView(new
Delagate_UpdateDataView(MainClass.MainForm.UpdateDataView));
}
}
The Update function in the Form
public void Process_UpdateDataView(Delagate_UpdateDataView update)
{
update();
}
public void UpdateDataView()
{
try
{
TagTableAdapter.Fill(uDataSet.PLC_Tag);
}
catch
{
}
}
Updating the TagTableAdapter manually works without any problem. Updating using the subscriber does nothing.
Probably there are easier ways to achieve this but I would like to use this type of construction also for other parts of the program.
Thanks for your suggestions.
Event's can only be risen from inside the class. If you could do that it would defeat the purpose of events.You can subscribe to this event from other class tho.
public event EventHandler someEvent;
EventContainer obj = new EventContainer();
obj.someEvent += handler;
where handler is a method according to the signature of someEvent. One is able to subscribe to the event from the outside just fine, but it can only be risen from inside the class defining it.
Suppose you have two classes:
public class A
{
int x = 0;
public void Increase()
{
x++;
}
}
public class B
{
A a;
private void DoSomething();
}
Is there a way for B to be "messaged" and execute DoSomething() when anything has changed in a (i.e. x has increased)? I know how I could make a subscribe to B, such that if B does RaiseSomeEvent(..), a reacts, but not the other way round.
Background: I'm trying to create a custom control
public class BattleshipCanvas : Canvas
{
public BSGrid BattleshipGrid {...}
...
}
that should redraw once anything inside the BattleshipGrid (BSGrid is a class encapsulating a two-dimensional array) changes, where BattleshipGrid will be bound to a certain BSGrid in the ViewModel. I thought about adding an event to BSGrid that is raised whenever I modify its data, but I don't know how to notify the BattleshipCanvas of that event.
I hope I could make it a little clear (it's hard for me to express what I want exactly here) and understandable, but if there arise any questions, feel free to comment and I'll try to answer them. Thanks!
You may be looking for events in c#. In your specific case you may like to make use of the INotifyPropertyChanged Interface. You can use it to inform other classes by events if a property inside the implementing class has changed.
This is also the base to use binding in your project later on.
public class A: INotifyPropertyChanged
{
//Event used to announce a change inside a property of your class
public event PropertyChangedEventHandler PropertyChanged;
int _x = 0;
public int X
{
get { return _x; }
set
{
if (_x != value)
{
_x = value;
OnPropertyChanged("X"); //invokes the event.
}
}
}
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) //make sure somebody subscribed to the event
handler.Invoke(this, new PropertyChangedEventArgs(propertyName)); //this calls all eventhandler methods which subscribed to your classes PropertyChanged event.
}
public void Increase()
{
X++; //use the property to invoke a property changed event.
}
}
public class B
{
A a;
public B()
{
a = new A();
a.PropertyChanged += new PropertyChangedEventHandler(a_PropertyChanged); //subscribe up to the event. (use -= to unsubscribe)
a.Increase()
}
//Catch the event
void a_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
//execute what you would like to do.
//you can use e.PropertyName to lookup which property has actually changed.
DoSomething();
}
private void DoSomething(){}
}
Events are probably the way to go. You can make any class in your project react to any event being raised in your program, no matter where the event is created/handled.
In your instance, it looks like you don't even need to send over any custom EventArgs.
The most simple example I could find of this is here:
http://timok.tumblr.com/post/57441520214/simplistic-event-example-in-c
This has taken me quite a few days to develop a demo of communicating between classes with delegates and events. I would like to know if this is the best practices way of accomplishing this passing of data between classes or not. If there is a better method please let me know. Specifically, if something happens in a subclass how do you get it back to the main class. This would be particularly useful when doing n-tier architecture by separating out the User Interface from the Business Logic Level, and the Data Access Level.
I have a form that has 3 text boxes: tb1, tb2, and tbAnswer.
I also have a button that says "Add" and it is just button1.
The main form is:
namespace DelegateTest
{
public delegate void ShowMessage(object sender, Form1.AnswerEventArgs e);
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void a_OnShowMessage(object sender, AnswerEventArgs e)
{
tbAnswer.Text = e.answer;
}
public class AnswerEventArgs :EventArgs
{
public string answer { get; set; }
}
private void button1_Click(object sender, EventArgs e)
{
AddClass a = new AddClass();
a.OnShowMessage += new ShowMessage(a_OnShowMessage);
a.AddMe(Convert.ToInt16(tb1.Text), Convert.ToInt16(tb2.Text));
}
}
}
and the subform called AddClass.cs is:
namespace DelegateTest
{
class AddClass
{
public event ShowMessage OnShowMessage;
public void AddMe(int a, int b)
{
Form1.AnswerEventArgs e = new Form1.AnswerEventArgs();
e.answer = (a+b).ToString();
OnShowMessage(this, e);
}
}
}
Your approach is sound except for two details.
First, a NullPointerException will occur if your event is raised before any handlers are added. You can get around this in one of two ways.
1) Make a local copy (to avoid race condition) and check it for null:
var showMessage = OnShowMessage;
if (showMessage != null)
{
showMessage(this, e);
}
2) Initialize your event to an empty delegate:
public event ShowMessage OnShowMessage = delegate { };
Second, you do not need to declare your own delegate in this case. You can simply create a standard EventHandler with your own event args:
public event EventHandler<Form1.AnswerEventArgs> OnShowMessage = delegate { };
See How to: Publish Events that Conform to .NET Framework Guidelines for more information.
Goal: Have a singleton publish events and allow any class to subscribe/listen to those events
Problem: I cannot figure out how to do this. The code below is illegal but it purveys what I'm trying to do
TransmitManager Class - Publisher
//Singleton
public sealed class TransmitManager
{
delegate void TransmitManagerEventHandler(object sender);
public static event TransmitManagerEventHandler OnTrafficSendingActive;
public static event TransmitManagerEventHandler OnTrafficSendingInactive;
private static TransmitManager instance = new TransmitManager();
//Singleton
private TransmitManager()
{
}
public static TransmitManager getInstance()
{
return instance;
}
public void Send()
{
//Invoke Event
if (OnTrafficSendingActive != null)
OnTrafficSendingActive(this);
//Code connects & sends data
//Invoke idle event
if (OnTrafficSendingInactive != null)
OnTrafficSendingInactive(this);
}
}
Test Class - Event Subscriber
public class Test
{
TrasnmitManager tm = TransmitManager.getInstance();
public Test()
{
//I can't do this below. What should my access level be to able to do this??
tm.OnTrafficSendingActive += new TransmitManagerEventHandler(sendActiveMethod);
}
public void sendActiveMethod(object sender)
{
//do stuff to notify Test class a "send" event happend
}
}
You shouldn't need to make the events static.
public event TransmitManagerEventHandler OnTrafficSendingActive;
public event TransmitManagerEventHandler OnTrafficSendingInactive;
Either your events have to be instance members or you have to address them as static.
TransmitManager.OnTrafficSendingActive +=...
OR
public event TransmitManagerEventHandler OnTrafficSendingActive;
...
TransmitManager.Instance.OnTrafficSendingActive+=...
Also: use EventHandler as your event delegate. Consider making a custom arguments class and pass the status to just one event instead of multiple events. This will let you pass status messages as well.
I have a User Control containing a bunch of controls. I want to set the default Event of this User Control to the Click event of one of my buttons.
I know for setting default event to one of the UserControl's events I should add the attribute:
[DefaultEvent("Click")]
public partial class ucPersonSearch : UserControl
...
I'm wondering if it's possible to do something like:
[DefaultEvent("btn1_Click")]
public partial class ucPersonSearch : UserControl
...
I want to fire some methods in the form hosting this User Control at the time btn1 is clikced.
This is really a knit in my project, and you're answer will be valueable.
You can't expose events of your class members to the outside of the class. How can others subscribe to the Click event of a Button inside your UserControl? Did you try it? It's not possible unless you make the button accessible from the outside, which is not good (everybody can change all the properties).
You have to define a new event, and fire your new event when your desired event (clicking on the button) happens:
[DefaultEvent("MyClick")]
public partial class UCPersonSearch : UserControl
{
Button btnSearch;
public event EventHandler MyClick;
public UCPersonSearch()
{
btnSearch = new Button();
//...
btnSearch.Click += new EventHandler(btnSearch_Click);
}
void btnSearch_Click(object sender, EventArgs e)
{
OnMyClick();
}
protected virtual void OnMyClick()
{
var h = MyClick;
if (h != null)
h(this, EventArgs.Empty);
}
}