Firing custom events / General event handling - c#

I'm getting into event handling now, and it seems quite confusing to me. See, I come from a web-dev background, so this event stuff is quite new to me.
I'm developing in C# / VS08 and created my Application in the WinForm-Designer.
Now, I created this program overview;
ProgramContext
MainForm : Form
LoginForm : Form
So, what I want to do is when the user clicks "Logout" (What is a menu item in the MainMenu of MainForm), that the application logs out the user.
But how can I access the "Click" event of the logout item from the ProgramContext's view, as there is all the logic of logging in etc.
I tried the following
MenuItem[] findLogout = MainMenuStrip.Items.Find("logoutMenuItem", true); // Throws NullPointerException
findLogout[0].Click += new EventHandler(LogoutClick);
private void LogoutClick(object sender, EventArgs e)
{
// Logout user
}
But keep getting a NullPointerException at the first line.

Easiest thing to do is to expose an event on MainForm:
public EventHandler LogOut;
Then hook into this from your ProgramContext:
MainForm form = new MainForm();
form.LogOut += new EventHandler(MainForm_LogOut);
void MainForm_LogOut(object sender, EventArgs e)
{
// Logout
}
Then fire the LogOut button is pressed on the MainMenu using the following code in the Menu Item's click event:
private void LogoutClick(object sender, EventArgs e)
{
if (LogOut != null)
{
LogOut(sender, e);
}
}

Related

Close Form when not clicking on it

I want to know if there is any event when you click on the rest of the screen and not the Windows Form the Form closes. Is it because of the ShowDialog()?
My Main Form is just with a notifyIcon and when I click it I call Form1.ShowDialog();
Main.cs:
private void ShowForm1(object sender, EventArgs e)
{
form1.Left = Cursor.Position.X;
form1.Top = Screen.PrimaryScreen.WorkingArea.Bottom - form1.Height;
form1.ShowDialog();
}
Form1.cs:
private void Form1_Load(object sender, EventArgs e)
{
label1.Text = "Test";
}
You need to run the dialog box non-modally, not modally. Think about it, when you run it modally, the dialog box takes over the UI and plays games with mouse-clicks elsewhere, preventing you from running. You don't want it to be modal anyway.
I created a simple Windows form with a button that includes this handler to open a small AutoCloseDialog form I created (and populated with a few controls):
private void button1_Click(object sender, EventArgs e)
{
var dlg = new AutoCloseDialog();
dlg.Show(this); //NOTE: Show(), not ShowDialog()
}
Then, in the AutoCloseDialog form, I wired up the Deactivate event. I did it in the designer (where this code is generated):
this.Deactivate += new System.EventHandler(this.AutoCloseDialog_Deactivate);
Finally, here is the handler for the Deactivate event.
private void AutoCloseDialog_Deactivate(object sender, EventArgs e)
{
this.Close();
}
I think this does what you are asking.
Yes, you can create a similar function like this, which closes the Form if the Form lost focus (in Form1.cs)
public void Form_LostFocus(object sender, EventArgs e)
{
Close();
}
and then you add the LoseFocus EventHandler (in Form1.Designer.cs):
this.LostFocus += new EventHandler(Form_LostFocus);

Why can I not call a form object in two events?

I'm making like a add contact form with two buttons, ADD CONTACT and EDIT CONTACT. When a user clicks add contact, it pops up another form where the user can add contact information.
I want to give them the option to edit that info by clicking the EDIT CONTACT button which should pop up the SAME form.
However its not letting me call the object of the form twice, saying that I cannot press the edit button after the add button.
How do I call a form object twice?
//instatiating an object of the form
FormContact contactForm = new FormContact();
public FormManager()
{
InitializeComponent();
}
private void btnAdd_Click(object sender, EventArgs e)
{
//displaying it when the user clicks add button
contactForm.Show();
}
private void btnEdit_Click(object sender, EventArgs e)
{
//trying to display it again but gives this exception
///System.ObjectDisposedException: 'Cannot access a disposed
///object.
///Object name: 'FormContact'.'
contactForm.Show();
}
Error:
///System.ObjectDisposedException: 'Cannot access a disposed
///object.
///Object name: 'FormContact'.'
The problem is you're closing the form after you've shown it.
You click the Show button
Your only instance of the form is shown
You close it with the X in the top corner
The runtime destroys the form (disposes it) after it is closed
You try to show it again but this this it's gone, trashed, doesn't exist any more, waiting to be garbage collected
Either make a new form each time you open it (to reduce code clutter, assign this same event handler to both button clicks, or copy paste it out twice if you want them to be coded differently eventually):
private void btnAddOrEdit_Click(object sender, EventArgs e)
{
new FormContact().Show();
}
Or intercept the FormClosing event of the FormContact form and cancel the closing, and perform a Hide() instead so that instead of being destroyed your form is made invisible. It will then still exist and can be Show()n the next time. To handle the event, open the FormContact designer, click anywhere in the form background, click lightning bolt in properties grid, double click the FormClosing entry:
private void FormClosing(object sender, FormClosingEventArgs e){
e.Cancel = true;
this.Hide();
}
Which method you choose depends how you want your program to behave:
If you make a new form each time, and you Show instead of ShowDialog your user could click Add twice and see two forms. Then could click Add 10 times and see 10 forms. Using ShowDialog means that the main window won't accept any more clicks until the FormContact is closed. You might or might not want this either
If you Hide (not close; hiding is different from closing) and Show the same form rather than making a new one then the user can click Add 10 times but they still only see one form
FormContact contactForm = new FormContact(); is a Member variable, it's scope is Private and is visible to the entire class.
After you first Show the form:
contactForm.Show();
The form is already showing. Therefore if you call Show again, it won't do anything as the instance of the form/class is already showing.
If you want to show two instances of the form, you will need to instantiate two instances eg:
private void btnAdd_Click(object sender, EventArgs e)
{
FormContact contactForm = new FormContact();
contactForm.Show();
}
private void btnEdit_Click(object sender, EventArgs e)
{
FormContact contactForm = new FormContact();
contactForm.Show();
}
Or make two instances of it:
FormContact contactForm1 = new FormContact();
FormContact contactForm2 = new FormContact();
private void btnAdd_Click(object sender, EventArgs e)
{
contactForm1.Show();
}
private void btnEdit_Click(object sender, EventArgs e)
{
contactForm2.Show();
}
Or add a argument in the parameter of the Constructor to indicate Add or Edit, eg:
public class FormContact
{
public FormContact(int id)
{
if (id > 0)
{
//Load contact for Editing
}
else
{
//Clear all fields for Adding
foreach(var ctrl in this.Controls)
{
if (ctrl Is TextBoxBase) ctrl.Text = string.Empty
//TODO other controls types... if (ctrl Is ....
}
}
}
}
Then you can call it passing a contactID to edit or 0 to add:
FormContact contactForm = new FormContact(contactID);
contactForm.Show();
I've got another answer, in both methods simply show your form modally:
contactForm.ShowModal();

Add event delegate to event handler of ASP.NET user control

I have a web user control in asp.net - a keypad. It has buttons for all digits, a textbox for display of input and clear and submit buttons. The user control sits in AJAX update panel so it can be easily shown/hidden. (App is destined for tablet browsers) I need to add a delegate to subMitButton ClickEventHandler inside my user control inside AJAX update panel. Any suggestions? Is it even possible? I don't want to use tablet's soft numeric keyboard because it is way to big. I could break my user control apart and use its code inside my web site but I'd rather use user control as intended.
you can raise an event from usercontrol which can be handled in the page .
You can declare a event
public event EventHandler SubmitButtonClick;
protected void OnSubmitButtonClick()
{
if (SubmitButtonClick!= null)
{
SubmitButtonClick(this, new EventArgs());
}
}
And then on the page, handle the event .
WebUserControl1.SubmitButtonClick+=
new WebUserControl.EventHandler(WebUserControl1_SubmitButtonClick);
private void WebUserControl1_SubmitButtonClick(object sender, EventArgs e)
{
Label1.Text = "Button Pressed";
}
Because of the ASP.NET webpage lifecycle I get Nulls when I set public properties on the user control from the main page. Those variables go out of scope once the page is sent to the client. However, here is an easy solution that will let you get notified when an event happens in your user control.
NOTE: There are some issues with Page.Context when back in the main page so changing things that effect the viewstate might not work.
Inside my user control i did the following...
// UC - setting up delegate and usercontrol property to store it
public delegate void CallbackAction(object sender, CustomEventArgs e);
public CallbackAction OnCallbackAction
{
get { return Session["CallbackAction"] as CallbackAction; }
set { Session["CallbackAction"] = value; }
}
Somewhere in the UserControl an event happens that you want to notify the main page of
// UC - callback from within the usercontrol
protected void UserControlButton_Click(object sender, EventArgs e)
{
if (IsPostback)
{
// do some processing
if (this.OnCallbackAction != null)
{
this.OnCallbackAction.Invoke(this, new CustomEventArgs("ET phone home") );
}
}
}
The structure above will now callback a main page that registers with the usercontrol. Here is how to register with the usercontrol from the main page
// Main Page - load event
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostback)
{
// register with usercontrol
this.UserControlFoo.OnCallbackAction += CallbackFromUserControl_Click;
}
}
// Main Page - this event will get called back when ET phones home
protected void CallbackFromUserControl_Click(object sender, CustomEventArgs e)
{
// phoned home from usercontrol
}

Handling an event on a dynamically-added Button after postback

Basically, I have an update panel in which i have a link button, when user clicks on the link button all the contents are cleared and textbox shows up in which user enters something and when user hit enter key, the update panel should be refreshed or gets updated or repopulated with all the contents .
How can I do it ???
The way I am trying to do this is that when event handler of link button is fired, I created a hidden button dynamically and assign it a new event handler which will get fired when user hits enter key.This new dynamic button is created inside link button event handler. In this new button event handler I will repopulate the contents back.
The problem with my way is the event handler of dynamically created button is not fired.
Why ???
Please try to answer in c#.
Thanks in advance.
Regards,
My code #
protected void Submit_Click1(object sender, EventArgs e)
{
Label1.Text = TextBox1.Text + TextBox2.Text + " are sucessfully registered";
Button mento = new Button();
mento.cssclass = "invisible";
mento.Click += new EventHandler(mento_click);
// here this new mento button is attached to update panel
updatepanel1.ContentTemplateContainer.Controls.add(mento);
}
Now the problem is mento_click event handler does not get fired ???
You can catch the enter key, in the textbox?
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
//add event keydown
textBox1.KeyDown += new KeyEventHandler(textBox1_KeyDown);
}
void textBox1_KeyDown(object sender, KeyEventArgs e)
{
switch (e.KeyCode )
{
case Keys.Enter:
//YOur updatecode here:
MessageBox.Show("You press enter");
break;
default:
break;
}
}
}
You have to attach the event on page_init or page_load every time theres a request, or the event wont get hooked up to the control.
you can check out this link to understand why:
http://msdn.microsoft.com/en-us/library/ms178472.aspx
Example
if you want to hook it up on the submit you should do something like:
page_init(object sender, EventArgs e)
{
CreateControls();
}
private void CreateControls()
{
//Create button with event and add to the panel
}
clickEvent(object sender, EventArgs e)
{
updatePanel.Update();
}
That should fire correctly the event. Im sorry i just wrote this on the fly and didnt test it, but i hope it gives you de general idea.
Cheers.
To all of you strugling with postback from buttons in asp.net, I would like to mention an alternative and ancient method of dealing with button-click events.
1) name your dynamically created buttons using a Prefix (like for instance this one: btn_). That way, every button you create will have a name starting with this prefix. For example the first button you create will have the name btn_0. You can achieve this by a routine like this one:
For _counter As Integer = 0 To 3
Dim butt As New Button
' the next 1 line is convenient when programming for the .net 4.0 framework:
butt.ClientIDMode = UI.ClientIDMode.Static
butt.butt.ID = "btn_" & _counter
butt.Text = "someting"
page.controls.add(butt)
next
2) ... and then, to handle it all, you can do it like this in the on_load event of your asp.net page:
If IsPostBack Then
For Each key As String In Request.Form
If InStr(Trim(key), "btn_") > 0 Then
Response.Write(Request.Form(key))
End If
Next
End If

Custom Component On Click Event

I've built a custom component that basically has a picture box and label in it. In the parent form, I want to be able to detect when its been clicked on. The standard .click event doesn't seem to be working, but I've never used events before so am unsure if I'm using them correctly. Heres the code I'm using (in the parent) to try and make it recognise the click:
Item aItem = new Item();
aItem.Icon = ItemImage;
aItem.Title = Title;
aItem.Click += new EventHandler(ItemClicked);
aItem.Filename = File;
and heres the method its calling:
public void ItemClicked(Object sender, EventArgs e)
{
MessageBox.Show("Item Clicked!");
}
This code never fires. Do I need to put anything into the component or am I just doing this wrong?
Cheers
Right I finally worked it out. Tejs response just confused me more so here's what I did.
In my UserControl I had the following event:
public event EventHandler Clicked;
Then I had an event for when the image was clicked (still in the UserControl) and I just called the Clicked event:
private void imgItem_Click(object sender, EventArgs e)
{
Clicked(this, e);
}
Then in my parent form, when I created the object, I had the following:
Item aItem = new Item();
aItem.Clicked += new EventHandler(ItemClicked);
void ItemClicked(object sender, EventArgs e)
{
MessageBox.Show("Clicked!");
}
You would do this by exposing an event':
Your custom component:
// A custom delegate like MyItemClickedHandler, or you could make a Func<> or Action<>
public event MyItemClickedHandler ItemClickedEvent;
public void ItemClicked(object sender, EventArgs e)
{
if(ItemClickedEvent != null)
ItemClickedEvent(); // Your delegate could pass parameters if needed
}
Then your parent form simply observes the event:
myCustomControl.ItemClickedEvent += new MyItemClickedHandler(SomeMethod);
Then, whenever the event is raised on your custom control, the parent is notified because it subscribed the event.

Categories

Resources