Following is the Code i am using
class ImpersonatedTab : System.Windows.Forms.TabPage
{
Credentials _cred = new Credentials();
public delegate void Savesetting(TabData Tb);
public event Savesetting TriggerSaveSetting;
public ImpersonatedTab(TabData tb)
{
........
}
private void SaveData()
{
TriggerSaveSetting(_tabdata);
}
private Onclick()
{
SaveData();
}
}
When i call Onclick function within ImpersonatedTab class it returns error saying TriggerSaveSetting is null
I initialize this call like
ImpersonatedTab Tab = new ImpersonatedTab(tb);
Tab.TriggerSaveSetting += new ImpersonatedTab.Savesetting(Tab_TriggerSaveSetting);
i have created events earlier, but am not able to figure out whats wrong with this one.. i am sure should be some silly mistake.
One possible case where this could happen is if you try to call the event from within the constructor of the ImpersonatedTab class. There where you put those .... Also it is a good practice to check if the event handler has been initialized before calling it.
Change your code to this:
public delegate void Savesetting(TabData Tb);
private Savesetting saveSettingDlg;
public event Savesetting TriggerSaveSetting {
add { saveSettingDlg += value; }
remove { saveSettingDlg -= value; }
}
private void SaveData() {
var handler = saveSettingDlg;
if (handler != null) handler(_tabdata);
}
You can now set a breakpoint on the add accessor and SaveData() and verify that event subscription is working correctly. If you do see the add accessor getting called but still get a null for handler then there's a problem with the object reference.
You are trying to invoke the TriggerSaveSetting event handlers before any handler was attached to it. Make sure, to check, the event has been some handlers attached:
private void OnTriggerSaveSetting(_tabdata)
{
if (TriggerSaveSetting != null)
TriggerSaveSetting(_tabdata);
}
Related
I tried like this but it will return null values,
public event EventHandler<EventArgs> myevent;
public void Btn_Click(object sender, EventArgs e)
{
if (myevent!= null) //Here I get null value.
myevent(null, new EventArgs());
}
How to achieve the event fire?
Edit:
I have a UserControl in that user control which contain button event,inside the ButtonClick method I created this event.
I have a Form. In that form i m using this UserControl. So i need to Fire a event from User Control button click event to Form page particular function.
I wrote up a very simple, and basic solution for you. Please read the comments in the code to make sense of the solution. If anything is unclear, please ask questions.
Below sample, will cause the event to fire, if the person's name changes:
Here is the Person object:
public class Person
{
//Event to register to, when you want to capture name changed of person
public event EventHandler<NameChangedEventArgs> nameChangedEvent;
//Property
private string _name;
public string Name
{
get { return _name; }
set
{
this._name = value;
//Call the event. This will trigger the OnNameChangedEvent_Handler
OnNameChangedEvent_Handler(new NameChangedEventArgs() {NewName = value});
}
}
private void OnNameChangedEvent_Handler(NameChangedEventArgs args)
{
//Check if event is null, if not, invoke it.
nameChangedEvent?.Invoke(this, args);
}
}
//Custom event arguments class. This is the argument type passed to your handler, that will contain the new values/changed values
public class NameChangedEventArgs : EventArgs
{
public string NewName { get; set; }
}
Here is the code that instantiates and uses the Person object:
class Program
{
static void Main(string[] args)
{
//Instantiate person object
var person = new Person();
//Give it a default name
person.Name = "Andrew";
//Register to the nameChangedEvent, and tell it what to do if the person's name changes
person.nameChangedEvent += (sender, nameChangedArgs) =>
{
Console.WriteLine(nameChangedArgs.NewName);
};
//This will trigger the nameChanged event.
person.Name = "NewAndrewName";
Console.ReadKey();
}
}
can you please try the below way of calling event :
public event EventHandler myevent;
myevent += new EventHandler(Button1_Click);
if (myevent != null) //Here I get null value.
myevent(1, new EventArgs());
My goal is to create an event, raise the event in Project #1, have Project #2 subscribe to the event so that I can hit some code in Project #2. I was advised to do it this way because I cannot reference the code in Project #2.
I'm not familiar with events and have been researching the last hour. Is there anyone that can provide example code on how to do this? What I have now is not working.
// Creating the event
public event EventHandler UpdateUIEvent;
// Raising the event in Project #1
protected override void ResetProperties()
{
this.filePath = string.Empty;
EventArgs e = new EventArgs();
UpdateUIEvent(this, e); // this kills my program
}
// Subscribing to the event in Project #2
protected override void ClearAll()
{
boEncrypt.UpdateUIEvent += new EventHandler ?? // Not sure how to subscribe here
tbFile.text = string.Empty;
}
You're close... Please read the docs as usual for a better understanding of what needs to be where.
For your code, here's what we'll do:
In project 1, incorporate Michael HB's good recommendation to always check if there's any subscribers.
public class ProjectOneClass
{
public event EventHandler UpdateUIEvent;
// other stuff
protected override void ResetProperties()
{
this.filePath = string.Empty;
EventArgs e = new EventArgs();
var handler = UpdateUIEvent;
if (handler != null)
UpdateUIEvent(this, e);
}
}
Then in project 2, you have to have a reference to the event, which means you also need a reference to the class that contains it. You define a method in the class in project 2 that has the same signature as the event in project 1. In your case (in many cases) this signature is void (object sender, EventArgs e). EventHandler is a pre-defined delegate with this signature.
"Subscribing" to the event is adding your new method to the handler, like pOne.UpdateUIEvent += SomeMethodWithTheSameSignature; You're basically saying "whenever UpdateUIEvent is called, call this other method as well".
So now that we know that we can have a method called when the event fires, we need to define that event. If you want to call ClearAll() when the event fires, that's what goes in the method body.
public class ProjectTwoClass
{
public ProjectOneClass pOne;
// other stuff
public ProjectTwoClass()
{
pOne = new ProjectOneClass();
pOne.UpdateUIEvent += POneOnUpdateUIEvent;
}
public void POneOnUpdateUIEvent(object sender, EventArgs eventArgs)
{
ClearAll();
}
private void ClearAll()
{
tbFile.Text = string.Empty; // could probably just call tbFile.Clear();
}
}
Before raising an event, you should always check if it is not null.
protected override void ResetProperties()
{
this.filePath = string.Empty;
EventArgs e = new EventArgs();
var handler = UpdateUIEvent;
if(handler != null)
UpdateUIEvent(this, e);
}
Even when you are in different projects, you should only matter about the "public" keyword (internal or private won't work).
In project #2, you'll have
protected overeride void ClearAll()
{
boEncrypt.UpdateUIEvent += yourFunctionToTriggerWhenTheEventIsRaised;
tbFile.text = string.Empty;
}
I want my C# code to call an event whenever a value is assigned to my object.
How exactly would I need to go about that?
class MyClass {
ManualResetEvent mre;
public MyClass() {
mre = new ManualResetEvent(false);
Data = null;
}
public object Data { get; set; }
void DataSet(object sender, EventArgs e) {
Console.WriteLine("object Data has been set.");
mre.Set();
}
}
Delegates don't seem to be what I need. An event, maybe? How would I write such an event, if so?
MyClass mc;
void processA() {
mc = new MyClass();
mc.Data = GetDataFromLongProcess();
}
private object data;
public object Data {
get { return data;}
set {
if(value != data) {
data = value;
OnDataChanged();
}
}
}
protected virtual void OnDataChanged() {
EventHandler handler = DataChanged;
if(handler != null) handler(this, EventArgs.Empty);
}
public event EventHandler DataChanged;
then hook any code to the DataChanged event. For example:
MyClass mc = ...
mc.DataChanged += delegate {
Console.WriteLine("new data! wow!");
};
If you want to fire an event when your property is set, you would do something like this:
public event Action OnDataChanged;
protected object _data = null;
public object Data
{
get { return _data; }
set
{
_data = value;
if(OnDataChanged != null)
OnDataChanged();
}
}
Then you would simply wire up event handlers to your object like so:
mc = new MyClass();
mc.OnDataChanged += delegate() { Console.WriteLine("It changed!"); };
mc.Data = SomeValue();
I think you're on the right track with an event-based model. Also take a look at the Observer pattern (which is the basis for .Net delegates and events underneath it all, as I understand):
http://www.dofactory.com/Patterns/PatternObserver.aspx
But the bottom line, as the other useful answer so far (Mr. Gravell's implementation) indicates, you're going to have to have code IN the setter to get it hooked up. The only alternative would be to poll the value for changes, which just smells bad to me.
you could implement INotifyPropertyChanged (this is more or less a event) or you could take your class a Action (Trigger) and call this, whenn the property changed.
Just don't use automatic properties but a concrete setter and call your event/trigger from there.
Conceptually, you would define an event in your class, and in your property set blocks, you would invoke the event with the necessary arguments to determine what just happened.
public event SomeDelegateThatTakesIntAsParameter myEvent;
void SetData(int data)
{
if(myEvent!= null)
myEvent(data)
}
I am making a windows forms project in C#, in which I made a class LabelX which inherits System.Windows.Forms.Label, then added a property Mass of float type
Now, my question is how can I handle, when value of Mass is changed.
e.g.:
When user enter value zero or less than zero
I want to fire a message that "Mass can't be zero or negative"
If I am interpreting this correctly, there are two parts to this. First, you need to detect invalid values and throw exceptions. Second, you need to raise an event when the property changes. This can be achieved as follows.
private float mass;
public float Mass
{
get
{
return this.mass;
}
set
{
if (value <= 0.0F)
{
throw new ArgumentOutOfRangeException("Mass cannot be zero or negative.");
}
if (this.mass != value)
{
this.mass = value;
OnMassChanged(EventArgs.Empty);
}
}
}
public event EventHandler MassChanged;
protected virtual void OnMassChanged(EventArgs args)
{
var handler = this.MassChanged;
if (handler != null)
{
handler(this, args);
}
}
To show a message if an invalid entry is made, you should put a try \ catch block around the call to set Mass and catch the ArgumentOutOfRangeException.
Try the following:
// Created an empty form with a LabelX control on it.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
// Added this event from the property manager.
private void labelX1_MassChanged(object sender, EventArgs e)
{
var label = (LabelX)sender;
if (label.Mass <= 0.0)
MessageBox.Show("Mass is less than or equal to 0");
}
}
public class LabelX : Label
{
private float _mass;
public float Mass
{
get { return _mass; }
set
{
if (!value.Equals(_mass))
{
_mass = value;
OnMassChanged(EventArgs.Empty);
}
}
}
public event EventHandler MassChanged;
protected virtual void OnMassChanged(EventArgs e)
{
if (MassChanged != null)
MassChanged(this, e);
}
}
Outside of your LabelX class, create the following class:
public class MassChangedEventArgs : EventArgs
{
public float Mass { get; private set; }
public MassChangedEventArgs(float mass)
{
this.Mass = mass;
}
}
Also outside of your LabelX class, create the following delegate. This will be your event handler.
public delegate void MassChangedEventHandler(object sender, MassChangedEventArgs e);
Within your LabelX class, create an event to broadcast:
public class LabelX
{
public event MassChangedEventHandler MassChanged;
//the rest of your code here...
}
You'll also want to create a private instance method that will fire your event.
public class LabelX
{
public event MassChangedEventHandler MassChanged;
private void OnMassChanged()
{
if(MassChanged!=null)
this.MassChanged(this, new MassChangedEventArgs(this.Mass));
}
//the rest of your code here...
}
Finally, whenever your Mass property changes, call OnMassChanged. For instance:
public class LabelX
{
private float mass;
public float Mass
{
get
{
return mass;
}
set
{
mass = value;
OnMassChanged();
}
}
public event MassChangedEventHandler MassChanged;
private void OnMassChanged()
{
if(MassChanged!=null)
this.MassChanged(this, new MassChangedEventArgs(this.Mass));
}
//the rest of your code here...
}
When you want to handle that event on a per-instance basis, you just have to register a listener with the MassChanged event of your underlying object and perform whatever actions are necessary.
Events are a common pattern used in the framework. The process typically involves defining a delegate to be used as the event handlers, declaring the event using the handler, defining methods to raise the event, then hooking up to the properties the logic to raise the event.
The message you describe is better done as an Exception but here's an example to define the MassChanged event.
// Define event args if you have additional
// information to pass to your event handlers
public class MassChangedEventArgs : EventArgs
{
public MassChangedEventArgs(int oldMass)
{
OldMass = oldMass;
}
public int OldMass { get; private set; }
}
public class SomeObject
{
// There's a generic event handler delegate that can be
// used so you only need to define the event arguments.
public event EventHandler<MassChangedEventArgs> MassChanged;
// Convenience method to raise the event
protected virtual void OnMassChanged(MassChangedEventArgs e)
{
if (MassChanged != null)
MassChanged(this, e);
}
public int Mass
{
get
{
return mass;
}
set
{
// Your checks here
if (value <= 0)
throw new ArgumentOutOfRangeException("Mass", "Mass can't be zero or negative");
// Should only raise the event if the new value is different
if (value != mass)
{
// Change the mass
MassChangedEventArgs e = new MassChangedEventArgs(mass);
mass = value;
// Raise the event
OnMassChanged(e);
}
}
}
private int mass;
}
After that, it's just a matter of registering handlers to the event and going from there.
I am quite sure you you would like to 'fire' an exception in your case.
This more of a validation logic issue such AOP code contracts concept.
But if you really like to create an event for it you have to at least:
1) create an event storage variable in your label class
public event EventHandler MassChanged;
2) in your property (note that you loose the ability to use code gen functions of c# 3 for
which 'auto' implement the field to store your Mass property value)
public bool Mass
{
get { return _mass; }
set {
// check if value is invalid (0 or less) && that event subscribers exist
if(value<=0 && MassChanged != null) { MassChanged(this, null); }
else // otherwise assign ...
{
_mass = value;
}
}
}
3) create an event handler of type EventHandler
Best to read the msdn article for events: link text
Again I am pretty sure you are not handling exceptions properly in the app
if you need an event for this. I mean there is nothing wrong but events are
usually not used as means of value validations.
I'm making custom events for C# and sometimes it isn't working.
This is how I'm making the event happen:
private bool isDoorOpen;
public bool IsDoorOpen {
get { return isDoorOpen;}
private set { isDoorOpen = value; DoorsChangeState(this, null);}
}
And these are the event declarations:
//events
public delegate void ChangedEventHandler(Elevator sender, EventArgs e);
public event ChangedEventHandler PositionChanged;
public event ChangedEventHandler DirectionChanged;
public event ChangedEventHandler BreaksChangeState;
public event ChangedEventHandler DoorsChangeState;
This works as long as there are methods attached to the events, but if there isn't, it throws a null ref exception. What am I doing wrong?
The recommended way to call an event is
var handler = this.DoorsChangeState;
if (handler != null)
handler(this, null);
The reason for copying the handler locally is incase the event handler changes on another thread while you're checking for null.
EDIT: Found the article talking about race conditions.
http://blogs.msdn.com/ericlippert/archive/2009/04/29/events-and-races.aspx
I know this question has been discussed (and answered) several times here on SO.
Also somewhere here i got the following extension methods to make this pattern more easy to use:
public static class EventHandlerExtensions
{
public static void FireEvent<T>(this EventHandler<T> handler, object sender, T args) where T : EventArgs
{
var temp = handler;
if (temp != null)
{
temp(sender, args);
}
}
public static void FireEvent(this EventHandler handler, object sender)
{
var temp = handler;
if (temp != null)
{
temp(sender, EventArgs.Empty);
}
}
}
So in your code you can say:
public bool IsDoorOpen
{
get { return isDoorOpen;}
private set
{
isDoorOpen = value;
DoorsChangeState.FireEvent(this);
}
}
If a event isn't subscribed to when it fires, a NullReferenceException will be thrown. This is correct behaviour, not something you've done wrong.
You should check:
if(DoorsChangeState != null)
{
DoorsChangeState(this, null); // Only fire if subscribed to
}
Before invoking an event you must check if the event is null:
if (DoorsChangeState != null)
DoorsChangeState(this, null);
When DoorsChangeState is null that means there are no listeners on that event.
You need to check to see if the event has been subscribed to.
I use this standard form for throwing all of my events.
var temp = EventName;
if(EventName!= null)
temp(this, null);