Delegate doesn't notify the method - c#

Would you look at my code and tell me where I went wrong? in following code I am trying to send a notification to myMethod() method when Form1 gets maximized.
Thanks!
namespace WindowsDelegate1
{
public delegate void ChangedEventHandler(object sender, EventArgs e);
class myForm : Form
{
public event ChangedEventHandler Changed;
protected virtual void OnChanged(EventArgs e)
{
if (Changed != null)
Changed(this,e);
}
public override System.Drawing.Size MaximumSize
{
//get
//{
// return base.MaximumSize;
//}
set
{
base.MaximumSize = value;
OnChanged(EventArgs.Empty);
}
}
}
}
namespace WindowsDelegate1
{
class EventListener
{
private myForm TheForm;
public EventListener(myForm theform)
{
TheForm = theform;
TheForm.Changed += new ChangedEventHandler(myMethod);
}
private void myMethod(object sender, EventArgs e)
{
MessageBox.Show("hey, window should be maximized now!");
}
public void Detach()
{
TheForm.Changed -= new ChangedEventHandler(myMethod);
TheForm = null;
}
}
}
Here is the testing unit / or main()
namespace WindowsDelegate1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
myForm f = new myForm();
EventListener listener = new EventListener(f);
f.ShowDialog();
f.WindowState = FormWindowState.Maximized;
listener.Detach();
}
}
}

What's probably happening is the event is either fired after your .Detach() call, or is never fired at all. I would start by removing the listener.Detach() call. Generally, you attach to events when the form is created or when it loads and detach when it is unloading.
Other than that, your Detach method is problematic because it tries to remove a different ChangedEventHandler instance than the one added. If you're wrapping your methods in ChangedEventHandler you need to store the instance you added.

Thank you for sharing your ideas!
I fixed it by removing the property (not idea why I used that!!) and using method instead by:
protected override void OnActivated(EventArgs e)
{
base.OnActivated(e);
OnChanged(EventArgs.Empty);
}
I have updated my source code above too

Related

c# label to receive information from private method(toolbox value)

I've created a new form, in which I have a toolbox. When I press a button in that form, it should relay that information that has been entered by the user(toolboxbox value) to the main form, in which it should say that piece of information in a label.
Since the method to create that username from the toolbox is private, I cannot access it from any other way. Making it public does not seem to make a difference, neither does get,set (from the way I've been trying to atleast).
Picture that may help explaining it:
Code (in which to create user):
namespace WindowsFormsApplication3
{
public partial class Newuserform : Form
{
public Newuserform()
{
InitializeComponent();
}
private void buttonCreateUser_Click(object sender, EventArgs e)
{
string uname = textboxUsername.ToString();
}
public void Unamecreate()
{
}
}
}
Form1 Code (To receive created user):
namespace WindowsFormsApplication3
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{
Application.Exit();
}
private void aboutToolStripMenuItem1_Click(object sender, EventArgs e)
{
Aboutform form2 = new Aboutform();
form2.Show();
}
private void newLocalUserToolStripMenuItem_Click(object sender, EventArgs e)
{
Newuserform formnewuser = new Newuserform();
formnewuser.Show();
}
}
}
you have a lot of options.
One way is to create an event and handle it in the main form.
public partial class Newuserform : Form
{
//the public property
public event EventHandler<string> UnameChanged;
public Newuserform()
{
InitializeComponent();
}
private void buttonCreateUser_Click(object sender, EventArgs e)
{
if (UnameChanged != null)
UnameChanged(textboxUsername.ToString()); //fire the event
}
}
Now, to "handle" the event, do the following in your main form:
private void newLocalUserToolStripMenuItem_Click(object sender, EventArgs e)
{
Newuserform formnewuser = new Newuserform();
formnewuser.UnameChanged += Handler;
formnewuser.Show();
}
private void Handler (object sender, string Uname)
{
// do something wit the new Uname.
}
note: recreating the Newuserform will require to cleanup previous attached resources.

c# Get variable value from Form when value changed with timer in usercontrol

I have a usercontrol which have timer
public partial class Cumle : UserControl
{
private bool cond=false;
//Some Code....
private void timer2_Tick(object sender, EventArgs e)
{
//Some Code....
if(//some condition...)
cond=true;
}
}
I am working on windows form.I want to display a message box which shows me that cond is true.I want to make this stuff without using timer on Form.
public partial class Form1 : Form
{
//What I must write here?
}
As mentioned, you should use Events. I would go like this:
public partial class Cumle : UserControl
{
public event EventHandler ConditionChangedToTrue;
protected virtual void OnConditionChangedToTrue(EventArgs e)
{
if (ConditionChangedToTrue != null)
ConditionChangedToTrue(this, e != null ? e : EventArgs.Empty);
}
private void timer2_Tick(object sender, EventArgs e)
{
//Some Code....
if (true) // add your condition
{
cond = true;
OnConditionChangedToTrue(null);
}
}
}
public partial class Form1 : Form
{
private Cumle cumle = new Cumle();
public Form1()
{
InitializeComponent();
cumle.ConditionChangedToTrue+= Cumle_ConditionChangedToTrue;
}
private void Cumle_ConditionChangedToTrue(object sender, EventArgs e)
{
// add your event handling code here
throw new NotImplementedException();
}
}
You need to add a public event to your UserControl, and subscribe to it from your main form.
Something like this should do it:
public partial class Cumle : UserControl
{
public event Action<bool> ConditionChanged = delegate {};
private bool cond=false;
//Some Code....
private void timer2_Tick(object sender, EventArgs e)
{
//Some Code....
if(//some condition...)
{
cond=true;
ConditionChanged(cond);
}
}
}
Then in your form:
public partial class Form1 : Form
{
void SubscribeToConditionChanged()
{
myUserControl.ConditionChanged += ShowDlg;
}
void ShowDlg(bool condition)
{
MessageBox.Show("....");
}
}

Delegate with generic list signature for passing data to another form

I'm quite new in C#, so I'm struggling with this more than two days. I hope that some one can help me out with this one.
Below some simplified code from my application.
I want to pass a List from Form1 to Form2 using delegate and event.
How can I do this? I read tons of explanations about events and delegates, but I still can't figure it out, how this really works.
Form1:
public delegate List<string> ProfileImportEventHandler();
public event ProfileImportEventHandler ProfileImported;
private void btnImport_Click(object sender, EventArgs e)
{
// raise an event
OnProfileImported();
}
protected virtual void OnProfileImported()
{
if (ProfileImported != null) // check if there are subscribers
{
ProfileImported();
}
}
Form2:
public partial class Form2 : Form
{
Form1 frm1;
public Form1()
{
// Constructor logic
frm1.ProfileChanged += new Form1.ProfileImportEventHandler(Form1_OnProfileImported);
}
}
List<string> Form1_OnProfileImported()
{
// TO DO
}
UPDATE
None of the solutions worked so far. Here is what I have already tried:
Form 2
// use generic list for profiles that will be imported from USB-Stick
private List<string> profilePaths = new List<string>();
public delegate void ProfileImportEventHandler(object sender, ProfileImportEventArgs e);
public event ProfileImportEventHandler ProfileImported;
public delegate void ImportButtonClickedEventHandler();
public event ImportButtonClickedEventHandler ButtonImportClicked;
public delegate void HaveDataDelegate(IList<string> data);
public event HaveDataDelegate HaveData;
//....
private void btnImport_Click(object sender, EventArgs e)
{
// do something...
// raise an event
var ea = new ProfileImportEventArgs(profilePaths);
OnProfileImported(ea);
OnButtonImportClicked();
// When there is data:
var copy = HaveData; // Use copy to avoid race conditions
if (copy != null)
{
copy(profilePaths);
}
// close form
this.Dispose();
}
protected virtual void OnProfileImported(ProfileImportEventArgs ea)
{
if (ProfileImported != null) // check if there are any subscribers
{
ProfileImported(this, ea);
}
}
protected virtual void OnButtonImportClicked()
{
if (ButtonImportClicked != null)
{
// fire event
ButtonImportClicked();
}
}
Form 1
public partial class frm_1 : Form
{
// child form
frm_2 frm2;
public frm_1()
{
InitializeComponent();
// do something...
// not sure if this is correct code and the correct place for it
frm2 = new frm_2();
frm2.ProfileImported += new frm_2.ProfileImportEventHandler(frm2_OnProfileImported);
//frm2.ProfileImported += frm2_OnProfileImported;
frm2.ButtonImportClicked += new frm_2.ImportButtonClickedEventHandler(frm2_ButtonImportClicked);
// In creation/init:
frm2.HaveData += DataFromForm2;
}
void frm2_OnProfileImported(object sender, ProfileImportEventArgs e)
{
// do something
}
void frm2_ButtonImportClicked()
{
// do something
}
private void DataFromForm2(IList<string> data)
{
// Process the data from Form2.
}
}
What am I still missing? Thank you for your help.
frm1.ProfileChanged += new Form1.ProfileImportEventHandler(Form1_OnProfileImported);
[…]
List<string> frmLoadProfileUSB_OnProfileImported()
First those names do not match. Second, with matching signatures you do not need (since C#2 if I recall correctly) to explicitly create the delegate. Thus:
frm1.ProfileChanged += frmLoadProfileUSB_OnProfileImported;
However, I think you have the event in the wrong place. It appears it is Form2 trying to pass data to Form1. Thus the event needs to be on Form2, with a delegate that is passed the data. Thus:
In Form2
public delegate void HaveDataDelegate(IList<string> data);
public event HaveDataDelegate HaveData;
// When there is data:
var copy = HaveData; // Use copy to avoid race conditions
if (copy != null) {
copy(data);
}
In Form1
// In creation/init:
Form2Instance.HaveData += DataFromForm2;
private void DataFromForm2(IList<string> data) {
// Process the data from Form2.
}
It's better not to use strong coupling.
So best solution here would be to store data in database or create proxy-object (class/struct).
like:
public (static) class ProfileChangesMonitor
{
...your logic here
}
If you want to use event handlers, you should follow the general pattern, defining a class that inherits EventArgs (supposing you want to involve a list in the event) in this way:
// Event Args
public class ProfileImportEventArgs : EventArgs {
private IList<string> list;
public ProfileImportEventArgs(IList<string> list) {
this.list = list;
}
public IList<string> List {
get {
return this.list;
}
}
}
// Event Handler Delegate
public delegate void ProfileImportEventHandler(object sender, ProfileImportEventArgs e);
// Form1:
public event ProfileImportEventHandler ProfileImported;
// ...
private void btnImport_Click(object sender, EventArgs e)
{
// raise an event
List<string> list = new List();
// Add something to list if needed
var ea = new ProfileImportEventArgs(list);
OnProfileImported(ea);
// Use ea.list here if necessary
}
protected virtual void OnProfileImported(ProfileImportEventArgs ea)
{
if (ProfileImported != null) { // check if there are subscribers
ProfileImported(this, ea);
}
}
// Form2:
public partial class Form2 : Form
{
Form1 frm1;
public Form1()
{
// Constructor logic
// TODO: Instantiate frm1 first.
frm1.ProfileImported += new Form1.ProfileImportEventHandler(Form1_OnProfileImported);
}
}
private void frmLoadProfileUSB_OnProfileImported(object sender, ProfileImportEventArgs e)
{
// Use and/or modify e.List if needed
}

Pass data between forms (event not triggered)

I am writing an application that passes gps data from a main form to a gps form at a constant interval (using a timer).
I've used the following tutorial to make a quick test:
http://www.codeproject.com/Articles/17371/Passing-Data-between-Windows-Forms
However, when I start the code no event is triggered. First I got a nullpointer. after adding the following lines I got rid of it:
if (GpsUpdated != null)
{
GpsUpdated(this, args);
}
Main form code:
public partial class Form1 : Form
{
// add a delegate
public delegate void GpsUpdateHandler(object sender, GpsUpdateEventArgs e);
// add an event of the delegate type
public event GpsUpdateHandler GpsUpdated;
int lat = 1;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
Form_GPS form_gps = new Form_GPS();
form_gps.Show();
timer1.Enabled = true;
}
private void timer1_Tick(object sender, EventArgs e)
{
Debug.WriteLine("Timer Tick");
// instance the event args and pass it each value
GpsUpdateEventArgs args = new GpsUpdateEventArgs(lat);
// raise the event with the updated arguments
if (GpsUpdated != null)
{
GpsUpdated(this, args);
}
}
}
public class GpsUpdateEventArgs : EventArgs
{
private int lat;
// class constructor
public GpsUpdateEventArgs(int _lat)
{
this.lat = _lat;
}
// Properties - Viewable by each listener
public int Lat
{
get
{
return lat;
}
}
}
GPS form code:
public partial class Form_GPS : Form
{
public Form_GPS()
{
InitializeComponent();
}
private void Form_GPS_Load(object sender, EventArgs e)
{
Debug.WriteLine("GPS Form loaded");
Form1 f = new Form1();
// Add an event handler to update this form
// when the ID form is updated (when
// GPSUpdated fires).
f.GpsUpdated += new Form1.GpsUpdateHandler(gps_updated);
}
// handles the event from Form1
private void gps_updated(object sender,GpsUpdateEventArgs e)
{
Debug.WriteLine("Event fired");
Debug.WriteLine(e.Lat.ToString());
}
}
Can anyone point me in the right direction? What am I doing wrong?
Thanks in advance and with best regards.
You should pass an instance of Form1 to your Form_GPS for it to work properly. See the following changes:
public partial class Form_GPS : Form
{
public Form_GPS(Form1 owner)
{
InitializeComponent();
owner.GpsUpdated += new Form1.GpsUpdateHandler(gps_updated);
}
private void Form_GPS_Load(object sender, EventArgs e)
{
Debug.WriteLine("GPS Form loaded");
}
// handles the event from Form1
private void gps_updated(object sender,GpsUpdateEventArgs e)
{
Debug.WriteLine("Event fired");
Debug.WriteLine(e.Lat.ToString());
}
}
Now you need to a small change in Form1 as well:
private void Form1_Load(object sender, EventArgs e)
{
Form_GPS form_gps = new Form_GPS(this);
form_gps.Show();
timer1.Enabled = true;
}
Notice how you pass an instance of Form1 to Form_GPS in the constructor of Form_GPS using the self reference this.
Declaring the event as following solved the problem:
public static event GpsUpdateHandler GpsUpdated;
instead of:
public event GpsUpdateHandler GpsUpdated;
In this way the Form1 event can be called static, so no new instance is necessary.

Calling a method of a parent page from UserController

I've followed this question and tried to build my solution. The problem is that 'UserControlButtonClicked' appears to be null! So 'UserControlButtonClicked(this, EventArgs.Empty)' inside the if, doesn't run, and the method 'addStepContent' in the parent page is never called.
UserControl 'StepsBar'
public sealed partial class StepsBar : UserControl
{
public event EventHandler UserControlAddStepContent;
[...]
public StepsBar()
{
this.InitializeComponent();
Image step_1 = new Image();
ButtonInfo step_1Info = new ButtonInfo();
step_1Info.Add((int)stepNumber.one, (int)stepStatus.normal);
step_1.Tag = step_1Info;
step_1.Source = setBackground((int)stepStatus.normal);
step_1.Tapped += stepTapped;
[...]
}
public void stepTapped(Object sender, RoutedEventArgs e)
{
[...]
if (step != null)
{
[...]
firePageEvent();
}
}
public void firePageEvent()
{
if (UserControlAddStepContent != null)
{
UserControlAddStepContent(this, EventArgs.Empty);
}
}
Parent Page
public Violation()
{
this.InitializeComponent();
StepsBar stepsBar = new StepsBar();
stepsBar.UserControlAddStepContent += new EventHandler(addStepContent);
}
private void addStepContent(object sender, EventArgs e)
{
CheckBox check_1 = new CheckBox();
check_1.Content = "Check me!";
bodyStackPanel.Children.Add(check_1);
}
This assumes that you want to use an existing delegate rather than make your own and you aren't passing anything specific to the parent page by event args.
In the user control's code-behind (adapt as necessary if not using code-behind or C#):
public partial class MyUserControl : System.Web.UI.UserControl
{
public event EventHandler UserControlButtonClicked;
private void OnUserControlButtonClick()
{
if (UserControlButtonClicked != null)
{
UserControlButtonClicked(this, EventArgs.Empty);
}
}
protected void TheButton_Click(object sender, EventArgs e)
{
// .... do stuff then fire off the event
OnUserControlButtonClick();
}
// .... other code for the user control beyond this point
}
In the page itself you subscribe to the event with something like this:
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
// hook up event handler for exposed user control event
MyUserControl.UserControlButtonClicked += new
EventHandler(MyUserControl_UserControlButtonClicked);
}
private void MyUserControl_UserControlButtonClicked(object sender, EventArgs e)
{
// ... do something when event is fired
}
}
Solved. The problem was this, on the parent page.
StepsBar stepsBar = new StepsBar();
stepsBar.UserControlAddStepContent += new EventHandler(addStepContent);
The istance of StepsBar was not added to the page. D'OH!
So here's what I've done:
stepsBar.UserControlAddStepContent += new EventHandler(addStepContent);
and on the xaml of the parent page:
<local:StepsBar x:Name="stepsBar"/>

Categories

Resources