problem in delegate program code - c#

I made this code in a class library named usedelegates:
namespace useofdelegates
{
public class Class1
{ //int i;
public delegate void mydelegate(object sender,EventArgs e);
public event mydelegate myevent;
public void fire()
{
EventArgs ee = new EventArgs();
myevent(this,ee);
}
}
}
Then in a windows form application, I intended to fire this event on the click of a button. The code in the form application is:
namespace WindowsFormsApplication9
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
useofdelegates.Class1 ob;
private void button1_Click(object sender, EventArgs e)
{
// ob = new useofdelegates.Class1();
***ob.fire();***//give exception as object reference not set to an instance of an object.*/
}
private void Form1_Load(object sender, EventArgs e)
{
useofdelegates.Class1 ob = new useofdelegates.Class1();
ob.myevent+=new useofdelegates.Class1.mydelegate(ob_myevent);
// ob.fire();
}
public void ob_myevent(object sender, EventArgs e)
{
MessageBox.Show("hello hapiness");
}
}
}
This code on compiling throws an exception:
Object reference not set to an instance of an object.
but when I call ob.fire() in form_load(), it gives me the desired result without any exception. Why is this happening?

Several things:
The ob object is not a class variable (field) so each function needs to initialize it, register the event and then call it. You are doing this on the form load, but not on the button click.
Or rather, looking at your code, you are hiding the field in your form load by using a method variable with the same name.
This should work fine:
useofdelegates.Class1 ob;
private void button1_Click(object sender, EventArgs e)
{
ob.fire();
}
private void Form1_Load(object sender, EventArgs e)
{
ob = new useofdelegates.Class1();
ob.myevent+=new useofdelegates.Class1.mydelegate(ob_myevent);
}
You also need to check that the delegate object is not null before calling it in the class that defines the event and delegate:
if (myevent != null)
myevent(this,ee);
The thread safe version is this:
mydelegate eventcopy = myevent;
if (eventcopy != null)
eventcopy(this,ee);

You are hiding the member declaration for ob by redeclaring it as a local variable in Form_Load. Here's the way it should look:
private void Form1_Load(object sender, EventArgs e)
{
ob = new useofdelegates.Class1();
ob.myevent+=new useofdelegates.Class1.mydelegate(ob_myevent);
// ob.fire();
}
You are probably getting a waring about this from your compiler. It's always a good idea to try to eliminate compiler warnings.

Related

How do I can call event from usercontrol to main form

I have a userControl and I've a button there, I'd like to call event when I'm clicking on the button in my main form from userControl. I do this:
UserControl
public UserControlerConstructor()
{
_button.Click += new EventHandler(OnButtonClicked);
}
public delegate void ButtonClickedEventHandler(object sender, EventArgs e);
public event ButtonClickedEventHandler OnUserControlButtonClicked;
private void OnButtonClicked(object sender, EventArgs e)
{
// Delegate the event to the caller
if (OnUserControlButtonClicked != null)
OnUserControlButtonClicked(this, e);
}
Form
public Form1()
{
userControlInstance.OnUserControlButtonClicked += new EventHandler(OnUCButtonClicked);
}
private void OnUCButtonClicked(object sender, EventArgs e)
{
throw new NotImplementedException();
}
It doesn't work because when I click in the form do nothing in the form code, but it does in userControl code. But I'd like to do in form code. I don't know how to call event from userControl to the form.
Well now I don't know if you're explicity want to use the delegate, no? If not, why don't you just do:
public Form1()
{
userControlInstance._button.Click += OnUCButtonClicked;
}
private void OnUCButtonClicked(object sender, EventArgs e)
{
throw new NotImplementedException();
}
up to now your code does not compile. You are using the wrong event handler type. It should show the following compiler error:
EventHandler cannot be converted to ButtonClickedEventHandler
Do the following steps:
1) put the declaration of the delegate outside of the class UserControlerConstructor:
public delegate void ButtonClickedEventHandler(object sender, EventArgs e);
public partial class UserControlerConstructor: UserControl
{
1) then change the type of the handler when registering the event in Form:
public Form1()
{
userControlInstance.OnUserControlButtonClicked += new ButtonClickedEventHandler(OnUCButtonClicked);
}
This way it should work

How to pass variable from event method?

I have a event method
private void button1_Click_1(object sender, EventArgs e)
with some code in it. There I want to use a variable from another event method called
public void textBox2_TextChanged(object sender, EventArgs e)
so if a user writes a number it gets saved in a variable in the second method and i want to use this variable in the first method where a button gets clicked. How do I pass it?
Save it as a field of your form class. You can then write it in one event handler and read it in another:
public partial class MyForm
{
private string _someValue = null;
public void TextBox2_TextChanged(object sender, EventArgs e)
{
_someValue = "Some New Value";
}
public void Button1_Click(object sender, EventArgs e)
{
if (_someValue != null)
{
// ...
}
}
}
Though perhaps you can just read TextBox2.Text in the second method.

Creating a universal boolean in C#

I write:
bool example = true under the code for say, a button event: private void button1_Click(object sender, EventArgs e)
I am trying to change the value of this bool when the user pushes a button.
The problem is, my bool is only recognized in this context. When I try to use it under private void checkBox1_CheckedChanged(object sender, EventArgs e) Visual Studio notifies me of an error saying the name doesn't exist in the context.
Where should I be putting the code for a bool?
Thanks.
Move it to class-level: that is, a member of the Form class:
public class YourForm : Form {
private bool _example = true;
// ... your event handlers here
private void checkBox1_CheckedChanged(object sender, EventArgs e) {
_example = false; // etc
}
}
Where should I be putting the code for a bool?
Outside of your methods, in the class level
public class MyForm : Form
{
// here is class level
public void SomeMethod()
{
// here is method level
}
}
As a member of the class;
public class MyClass
{
private bool example = false;
private void button1_Click(object sender, EventArgs e)
{
example = true;
}
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
//example available
}
}
Use static variable or class level.

Call public parent function from child class

Inside my Main method I'm instantiating the UpdateDialog class inside which based on if the user presses a button or not I need to call function1() from Main. Here is the code:
public partial class Main : Form
{
public void function1()
{
doing_stuff_here();
}
private void button1_Click(Object sender, EventArgs e)
{
var update = new UpdateDialog();
update.ShowDialog();
}
}
public partial class UpdateDialog : Form
{
private void button2_Click(object sender, EventArgs e)
{
//call here function1() from Main
}
}
What should I do to be able to call function1() from Main inside the partial class UpdateDialog?
LE: although the method suggested by Styxxy seems right it doesn't work well in my app because of cross-thread invalid operation so I ended up using the delegate workaround suggested by Cuong Le.
You'll have to have an instance of the Main form in your UpdateDialog form. As you say that UpdateDialog is a child form of your Main form, I guess that you create the UpdateDialog in your Main form and do a show there. Before showing that form, you could assign the Parent property.
var updateDialog = new UpdateDialog();
// Or use "UpdateDialog updateDialog = new UpdateDialog();" as people like Andreas Johansson don't like the "var" keyword
// Do other stuff here as well
updateDialog.Parent = this;
// Or use Show() for non modal window
updateDialog.ShowDialog();
You get the error ArgumentException: Top-level control cannot be added to a control.. Now this can be solved in two ways.
You can set the TopLevel property to false on your Main form (I'm not a huge fan of this).
You can use the Owner property to your Main form (this). Below two ways of doing it.
You can set the Owner manually:
updateDialog.Owner = this;
Or you can add this as parameter to the Show(owner) or ShowDialog(owner) methods; this way, the Owner is also being set.
updateDialog.Show(this);
// or
updateDialog.ShowDialog(this);
"Full" code makes this:
var updateDialog = new UpdateDialog();
// Do other stuff here as well
updateDialog.Owner= this;
updateDialog.ShowDialog(); // or use .Show()
// or
updateDialog.ShowDialog(this); // or use .Show(this)
I suggest you create an event in UpdateDialog then subscribe it after you create an instance inside the Main class. This way you have a better separation between these 2 classes.
public partial class Main
{
public void function1()
{
doing_stuff_here();
}
private void button1_Click(object sender, EventArgs e)
{
var update = new UpdateDialog();
update.OnButton2Click += OnUpdateDialogButton2Click;
update.ShowDialog();
}
void OnUpdateDialogButton2Click(object sender, EventArgs e)
{
function1();
}
}
public partial class UpdateDialog
{
public event EventHandler<EventArgs> OnButton2Click;
private void button2_Click(object sender, EventArgs e)
{
//call here function1() from Main
if (OnButton2Click != null)
{
this.OnButton2Click(this, e);
}
}
}
Pass Main class instance to your Update Form and store it in instance variable -
Main mainWindow = null;
public UpdateDialog(Main mainForm)
{
mainWindow = mainForm;
}
private void button2_Click(object sender, EventArgs e)
{
mainWindow.function1();
}
And from Main method -
private void button1_Click(Object sender, EventArgs e)
{
var update = new UpdateDialog(this);
update.ShowDialog();
}
You could turn it around, and let Main form listen to clicks from the UpdateDialog.
In Main:
private void button1_Click(Object sender, EventArgs e)
{
var update = new UpdateDialog();
update.OnSomethingClicked += function1;
update.ShowDialog();
}
void form_OnSomethingHappened(object sender, EventArgs e)
{
// Do the stuff you want
}
In UpdateDialog:
public event EventHandler OnSomethingHappened;
private void button2_Click(object sender, EventArgs e)
{
EventHandler handler = OnSomethingHappened;
if (handler != null) handler(this, e);
}
The ShowDialog() method returns a DialogResult you can call function1 one of after the dialog is closed.
http://msdn.microsoft.com/en-us/library/c7ykbedk.aspx
Can pass the Main class like a reference.
For example:
public partial class Main : Form
{
//make it internal, if UpdateDialog in the same assembly, and it only one that would use it. In other words hide it for outside world.
internal void function1()
{
doing_stuff_here();
}
....
}
public partial class UpdateDialog : Form
{
private MainForm _main = null;
public UpdateDialog (MainForm main) { //Accept only MainForm type, _not_ just a Form
_main = main;
}
private void button2_Click(object sender, EventArgs e)
{
_main.function1(); //CALL
}
}
Something like this. You can change this accroding to your precise requirements, but this is a general idea.
Approach #1
You need to create an instance of class Main.
Main foo = new Main();
foo.function1();
Approach #2
You need to declare the method as static.
public static function1(){ ... }
....
Main.function1();
You can make your function1 a Partial method and this way you can use it in all your partial classes.
Partial methods allow the definition of a method to be located in one file and the body of the method to be optionally defined in another file. They can only be used in partial classes and were introduced as language features in C# 3.0 and Visual Basic 9.0, the versions that shipped with the .NET Framework 3.5 and Visual Studio 2008.
So what you can do is modify like this
public partial class Main : Form
{
public partial void function1()
{
doing_stuff_here();
}
private void button1_Click(object sender, EventArgs e)
{
var update = new UpdateDialog();
update.ShowDialog();
}
}
public partial class UpdateDialog : Form
{
public partial void function1();
private void button2_Click(object sender, EventArgs e)
{
function1();
}
}

call event from form2 in form1

hi
call event from form2 in form1?
for example :
The following code into form2 :
private void Form2_Load(object sender, EventArgs e)
{
MessageBox.Show("http://stackoverflow.com");
}
What to write in a form1?
Why are you wanting to call the event? Will you know the sender and the Event Args?
Why don't you just create a public method in Form2 that Form1 is able to see?
how about form2.Form2_Load(this, null)
You can't call private members of a class from outside it.
You can change the accessibility to internal, which will make it visible within the assembly - if your form1 is in the same assembly.
Alternatively you can make it a public method, which would make it globally accessible.
However, you shouldn't call event handlers in such a manner - they are supposed to handle events that the declaring class raises.
For the sample code you gave, a better solution would be to create a public or internal method that can be called from this event handler:
private void Form2_Load(object sender, EventArgs e)
{
MyMethod();
}
public MyMethod()
{
MessageBox.Show("http://stackoverflow.com");
}
In order to call this method from form1, it needs to know about form2:
// in form1
Form frm2 = new Form2();
frm2.MyMethod();
You can't raise an Event from outside a class.
The convention is that you call a OnEventname method in the class. Usually this method is protected (can't only accessed from the class itself or others that inherit from it)
// in form1
private void Method1()
{
using (var form2 = new Form2())
{
form2.Show();
form2.RaiseLoadEvent(EventArgs.Empty);
}
}
// Create this method in form2
public void RaiseLoadEvent(EventArgs e)
{
OnLoad(this, e);
}
// The OnLoad method already exists in form 2
// But it usually looks like this
protected void OnLoad(EventArgs e)
{
var eh = LoadEventHandler;
if (eh != null)
{
eh(this, e);
}
}
But I don't suggest to raise the LoadEvent, because It is raised only once after the creation of the form. More usual is to react to the Load event to modify the form.
privat void Method1()
{
using (var form2 = new Form2())
{
// Add Event Handler
form2.Load += new EventHandler(form2_Load);
form2.ShowDialog();
}
// Allways remove Event Handler to avoid memory leaks
form2.Load -= new EventHandler(form2_Load);
}
private void form2_Load(object sender, EventArgs e)
{
form2.Text = "Hello from form1";
}
Form1 (the event publisher) should expose a separate, public event property for Form2 (the subscriber) to subscribe to.
For example: the form publishing the event will look like this:
public partial class Publisher : Form
{
public event PostUpdateHandler OnPostUpdate;
public Publisher()
{
InitializeComponent();
new Subscriber(this).Show();
}
private void button1_Click(object sender, EventArgs e)
{
if (OnPostUpdate != null)
{
OnPostUpdate(new PostUpdateArgs(textBox1.Text));
}
}
}
public delegate void PostUpdateHandler(PostUpdateArgs args);
public class PostUpdateArgs : EventArgs
{
public string UpdateText;
public PostUpdateArgs(string s)
{
UpdateText = s;
}
}
The subscribing form looks like this:
public partial class Subscriber : Form
{
public Subscriber()
{
InitializeComponent();
}
public Subscriber(Publisher publisher) : this()
{
publisher.OnPostUpdate += new PostUpdateHandler(publisher_OnPostUpdate);
}
private void publisher_OnPostUpdate(PostUpdateArgs args)
{
this.Form2_Load(null, null);
}
private void Subscriber_FormClosed(object sender, FormClosedEventArgs e)
{
this.Dispose();
}
private void Form2_Load(object sender, EventArgs e)
{
MessageBox.Show("http://stackoverflow.com");
}
}
When the user presses button1 on the publishing form, the subscribing form will execute the code associated with the delegate, resulting in a message box popping up with the message http://stackoverflow.com.

Categories