:How to create a event in c# without delegates? - c#

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());

Related

c# DataChanged event does trigger on a windows form (Desktop Application)

I have a form, I select some checkboxes, edit some text field, select from a combobox etc. then I click Exit. Based on the fact that "Data has been changed ??" I wish to perform actions. The problem is I can't get the event work :
private void DataChanged(object sender, EventArgs e)
{
MessageBox.Show("Data is changed", "debug");
isDataSaved = false;
}
When is this method called, how do I make it work? Is this supposed to get fired when the form's fields have some data i.e filL a text box ?
I dont really get the API: DataChanged event
Note: I'm following Mike Murach C# 5th edition chapter 10 example.
Edit (exact words from book):
Generate an event handler named DataChanged for the
SelectedIndexChanged event of the XXXX Name combo box. Then , wire
this event handler to the TextChanged event of the YYYYY Method label
and add the code to this event handler so it sets the isDataSaved
variable to false
When I double click on the commbo box the generated event handler it is not named DataChanged but cboNames_SelectedIndexChanged... (is this a book screw up or me total noob ? PS: There is no .. 'database' in the project)
Personally I mostly use databinding these days to get notified of changes in data.
A data holder class, which implements INotifyPropertyChanged. This interface gives you the possibility to get notified when the value of a property changes.
public class SomeData: INotifyPropertyChanged {
public event PropertyChangedEventHandler PropertyChanged;
private void SetProperty<T>(ref T field, T value, [CallerMemberName] string name = "") {
if (!EqualityComparer<T>.Default.Equals(field, value)) {
field = value;
var handler = PropertyChanged;
if (handler != null) {
handler(this, new PropertyChangedEventArgs(name));
}
}
}
private boolean _someBoolean;
public int SomeBoolean {
get { return _someBoolean; }
set {
SetProperty(ref _someBoolean, value);
}
}
private string _someString;
public string SomeString {
get { return _someString; }
set {
SetProperty(ref _someString, value);
}
}
// etc
}
Now our form, which uses the data class and it's INotifyPropertyChanged implementation to get notified when a change in data occurs.
public partial class SomeForm: Form {
private SomeData _data;
private void LoadData() {
_data = new SomeData();
_data.PropertyChanged += Data_PropertyChanged;
}
private void SaveData() {
// TODO: Save data
}
private void AddDataBindings() {
checkbox1.DataBindings.Add("Checked", _data, "SomeBoolean");
textbox1.DataBindings.Add("Text", _data, "SomeString");
// add other
}
private void Data_PropertyChanged(object sender, PropertyChangedEventArgs e) {
// Here you can add actions that must be triggered when some data changes.
if (e.PropertyName == "SomeBoolean") {
// Do something when some-boolean property changes
}
// Set is-changed-boolean to true to 'remember' that something has changed.
_isChanged = true;
// Give message
MessageBox.Show(string.Format("Data changed, property {0}", e.PropertyName));
}
private bool _isChanged = false;
protected void Form_Closed(object sender, EventArgs e) {
// If data is changed, save it
if (_isChanged) {
SaveData();
}
}
}
Your problem is not known where the method DataChanged use and how. I have a suggestion for you that is use Focus Activated in properties.Add datachanged printing method Activated
good luck.
You must make properties this like

Getting update from UserControl

Can someone tell me how can I have a feature in my UserControl, that can let the host windowsform know what is the control is doing?
For example my usercontrol has a filebrowser, and if user uses this file browser to open a file I want in the statusstrip bar of my form to write "Loading file(s)".
Will this require using events? if so, how can I have a single event inside usercontrol to report anything it does (then I guess I have to call this event in all methods in the usercontrol).
Simple
Yes, expose an event on the user control that the Form can subscribe to. You should use the standard event pattern:
class MyUserControl : UserControl
{
public event EventHandler<EventArgs> FileOpened;
protected virtual void OnFileOpened(EventArgs e)
{
EventHandler<EventArgs> handler = FileOpened;
if (handler != null)
handler(this, e);
}
}
Then when the file is opened you call OnFileOpened(EventArgs.Empty) which fires the event.
With custom EventArgs
Now the Form probably needs to know what file was opened. You could expose a property on the user control that the Form can use to find out, or you can provide that information in your event like so:
public class FileOpenedEventArgs : EventArgs
{
private string filename;
public FileOpenedEventArgs(string filename)
{
this.filename = filename;
}
public string Filename { get { return filename; } }
}
class MyUserControl : UserControl
{
public event EventHandler<FileOpenedEventArgs> FileOpened;
protected virtual void OnFileOpened(FileOpenedEventArgs e)
{
EventHandler<FileOpenedEventArgs> handler = FileOpened;
if (handler != null)
handler(this, e);
}
}
Then you fire the event with OnFileOpened(new FileOpenedEventArgs(filename)).
Optimal
When you create an event handler public event delegate Name;, you are allocating storage for the delegate on your object. Objects (especially Controls) often have a huge number of events that are never subscribed to. That's a whole lot of allocated storage not being used. There's an optimization built into the framework in the form of a EventHandlerList. This handy object stores event handlers only when they are actually used. All System.Windows.Forms.Control objects derive from System.ComponentModel.Component and it already provides an (protected) EventHandlerList that you can access in your derived Control.
To use it, you first create a static object that uniquely identifies your event, and then you provide the add {} and remove {} methods manually. Like so:
class MyUserControl : UserControl
{
private static readonly object FileOpenedKey = new Object();
public event EventHandler<FileOpenedEventArgs> FileOpened
{
add { Events.AddHandler(FileOpenedKey, value); }
remove { Events.RemoveHandler(FileOpenedKey, value); }
}
protected virtual void OnFileOpened(FileOpenedEventArgs e)
{
var handler = (EventHandler<FileOpenedEventArgs>)Events[FileOpenedKey];
if (handler != null)
handler(this, e);
}
}
Yes, you will need to create an event and subscribe to it. One suggestion following the standard pattern for events:
enum ControlStatus {Idle, LoadingFile, ...}
class StatusChangedEventArgs : EventArgs
{
public ControlStatus Status {get; private set;}
public StatusChangedEventArgs(ControlStatus status)
: base()
{
this.Status = status;
}
}
partial class MyControl : UserControl
{
public ControlStatus Status {get; private set;}
public event EventHandler<StatusChangedEventArgs> StatusChanged;
protected virtual void OnStatusChanged(StatusChangedEventArgs e)
{
var hand = StatusChanged;
if(hand != null) hand(this, e);
}
void LoadFiles()
{
...
Status = ControlStatus.LoadingFiles;
OnStatusChanged(new StatusChangedEventArgs(this.Status));
...
Status = ControlStatus.Idle;
OnStatusChanged(new StatusChangedEventArgs(this.Status));
}
}
partial class MyHostWindowsForm : Form
{
public MyHostWindowsForm()
{
var ctl = new MyControl();
...
ctl.StatusChanged += ctl_StatusChanged;
}
void ctl_StatusChanged(object sender, StatusChangedEventArgs e)
{
switch(e.Status)
{
case ControlStatus.Idle:
statusStripBar.Text = null;
break;
case ControlStatus.LoadingFiles:
statusStripBar.Text = "Loading file(s)";
break;
...
}
}
}

How to write a Trigger?

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)
}

Custom event handler not getting initialized

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);
}

Windows Forms application, how to communicate between custom controls?

I have three user controls. Here are the description of them:
1) First user control(ucCountry) contains combobox which displays country names from an xml file.
2) Second user control(ucChannelType) contains two radio buttons one to select TV and other to select Radio Channel Type.
3) Third usercontrol(ucChannels) will populate all the channels where country name is provided by ucCountry and type provided by ucChannelType
Now, how to communicate between these user control in a form. I need to decouple the usercontrols from the form. So, I need to use events. But if ucCountry fires an event (say CountryChanged event) and ucChannels subscribe the event, how to get the channel type from ucChannelType.
Thanks in advance...
best solution is to add properties to your custom controls. there may be no fields in background, the getters will just get data from property of internal standard control.
You could either have a property on ucCountry which provides the currently selected country. Something like:
public Country SelectedCountry
{
get
{
return (Country) myComboBox.SelectedItem;
}
}
And then when the event fires, the other controls go a get the property.
The other option is to use a custom event delegate, so the event handler for ucCountry.CountryChanged would have a country parameter:
public delegate void CountryChangedDelegate(Country sender)
public event CountryChangedDelegate CountryChanged;
Event handler in ucChannels:
public void ucCountry_CountryChanged(Country sender)
{
//do something with the new country
}
And wire the event to ucChannels:
myUcCountry.CountryChanged += new CountryChangedDelegate(ucCountry_CountryChanged);
You need to have public properties for the controls supplying data, and a public method to register events to for the control consuming the data. Here's a quick example:
public static void Test()
{
var a = new A();
var b = new B();
var c = new C() {a = a, b = b};
a.OnChange += c.Changed;
b.OnChange += c.Changed;
a.State = "CA";
b.ChannelType = "TV";
}
class A
{
private string _state;
public string State
{
get { return _state; }
set
{
_state = value;
if (OnChange != null) OnChange(this, EventArgs.Empty);
}
}
public event EventHandler<EventArgs> OnChange;
}
class B
{
private string _channelType;
public string ChannelType
{
get { return _channelType; }
set
{
_channelType = value;
if (OnChange != null) OnChange(this, EventArgs.Empty);
}
}
public event EventHandler<EventArgs> OnChange;
}
class C
{
public A a { get; set; }
public B b { get; set; }
public void Changed(object sender, EventArgs e)
{
Console.WriteLine("State: {0}\tChannelType: {1}", a.State, b.ChannelType);
}
}

Categories

Resources