I use OnPropertyChanged("property"); to raise the event via a setter of a property.
Class1.xaml.cs:
public Class1()
{
InitializeComponent();
Class2.PropertyChanged += delegate
{
// do stuff
};
}
In Class2.cs I have the following:
public static event PropertyChangedEventHandler PropertyChanged = delegate { };
public static void OnPropertyChanged(string property)
{
PropertyChanged(null, new PropertyChangedEventArgs(property));
}
The delegate in Class1 executes one time. Class2 works as expected. I checked this with breakpoints.
What happens in order is:
Class2 fires event
Class1 handles event
Class2 fires event
Class2 fires event
Also, when I remove = delegate { } the second time the handler is null.
How can I handle the event in Class1 every time it fires in Class2?
EDIT:
My project structure is the following:
App
Location of Class1, main project.
App.Shared
Location of Class2, shared logic for main and background project.
App.Background
Background project for
IBackgroundTask. Here I call OnPropertyChanged("property").
Related
I am having some issues with handling an event that I am raising in a separate DLL in a separate exe. I have a class that subscribes to the event in another DLL. When I raise the event, by the time I get to the event handling, the event handler is null since the object that subscribed to it exists in separate call stack. Is there a clean way to handle something like this?
Public class B is in another dll on another executable (same solution) than Class A.
public static class CustomEvent
{
public static event EventHandler<CustomEventArgs> eventHandler;
public static void Raise(CustomEventArgs args)
{
// When class B raises the event. The eventHandler here is null.
// Meaning it doesn't know that Class A has subscribed to the event.
EventHandler<CutomEventArgs> handler = eventHandler;
if(handler != null)
{
eventHandler(typeof(CustomEvent), args);
}
}
}
public class A
{
public class A ()
{
CustomEvent.eventHandler += HandleEvent;
}
public class B
{
public void Function()
{
CustomEvent.Raise(new CustomEventArgs());
}
}
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
I have a base-class (let it be SomeBaseClass) containing a public event (SomeEvent) and I have a derived-class in which I want to raise this event but I can't(!!) VS 2010 says me (in derived-class in line: base.SomeEvent != null) "The event 'SomeBaseClass.SomeEvent' can only appear on the left hand side of += or -=". If I replace base on this It is make no sense.
No, it's absolutely right - the event is only an event (with subscription and unsubscription) as far as a derived class is concerned. If your base class wants to let derived classes raise the event, it should include a protected method to do so (typically a virtual OnFoo(EventHandler) for an event called Foo with the EventHandler type, for example). Note that if you write a field-like event in C# like this:
public event EventHandler Foo;
That's actually declaring a private field called Foo (which that class and any nested classes have access to) and a public event (which consists only of subscribe/unsubscribe). You could declare your own "custom" event like this:
protected EventHandler foo;
// Note: not thread-safe. Only present for demonstration purposes.
public event EventHandler Foo
{
add { foo += value; }
remove { foo -= value; }
}
and then derived classes would have access to the field... but I wouldn't recommend that. (I rarely declare non-private fields, other than for constants.)
You need to do it the right way (i.e., the idiomatic way in C#)
public class Base {
public event EventHandler<EventArgs> SomeEvent;
protected virtual void OnSomeEvent(EventArgs e) {
EventHandler<EventArgs> handler = SomeEvent;
if (handler != null) {
handler(this, e);
}
}
}
public class Derived {
protected virtual void OnSomeEvent(EventArgs e) {
// derived event handling here
// then invoke the base handler
base.OnSomeEvent(e);
}
}
The reason that you do it like this is because events can only be invoked from within the defining class.
Does anybody know what's kind of event happend on target control when I use errorProvider.SetIconAlignment() method?
for example:
When I call errorProvider.SetIconAlignment(mytextbox1, ErrorIconAlignment.MiddleRight);
on mytextbox1 I want to catch this event whenever SetIconAlignment was called?
I don't see an event that ErrorProvider could be using. In fact, I can't find any event at all that's related to this.
Based on what I've used from ErrorProvider, there is no other way than to extend the method, like this:
// Defines an extended version of the ErrorProvider
public class ExtendedErrorProvider : ErrorProvider, INotifyPropertyChanging, INotifyPropertyChanged
{
// That will replace the SetIconAlignment from the base class when you call it from outside the class
public void SetIconAlignment(Control control, ErrorIconAlignment value)
{
// Will raise an event just before changing the property
OnPropertyChanging("IconAlignment");
// Changed the property using the base class
base.SetIconAlignment(control, value);
// Will raise an event just after the property has changed
OnPropertyChanged("IconAlignment");
}
// This will ensure that whenever you bind methods to be called on the PropertyChanging, they will get called for the specific property...
protected void OnPropertyChanging(string property) { if (PropertyChanging != null) PropertyChanging(this, new PropertyChangingEventArgs(property)); }
public event PropertyChangingEventHandler PropertyChanging;
// This will ensure that whenever you bind methods to be called on the PropertyChanged, they will get called for the specific property...
protected void OnPropertyChanged(string property) { if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(property)); }
public event PropertyChangedEventHandler PropertyChanged;
}
Now, outside this class, you can do something like this:
errorProvider1.PropertyChanging += WhatNeedsToBeDoneBeforeChanging(...);
errorProvider1.PropertyChanged += WhatNeedsToBeDoneAfterChanging(...);
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.