Adding events to Form designer file - c#

I created a new Event in my user control (SearchControl) like this:
//Event which is triggered on double click or Enter
public event EditRecordEventHandler EditRecord;
public delegate void EditRecordEventHandler(object sender, EventArgs e);
//Supressing the events
private bool _raiseEvents = true;
private void OnEditRecord(System.EventArgs e)
{
if (_raiseEvents)
{
if (this.SearchResultGridView.FocusedRowHandle > -1)
{
if (EditRecord != null)
{
EditRecord(this, e);
}
}
}
}
Now this Event is called when user double click a row in a grid. So from the properties window I selected the MouseDoubleClick Event of the grid view and called the above created EditRecord event.
private void SearchResultListGridControl_MouseDoubleClick(object sender, MouseEventArgs e)
{
// Check whether the user clicked on a real and not a header row or group row
DevExpress.XtraGrid.Views.Grid.ViewInfo.GridHitInfo info = SearchResultGridView.CalcHitInfo(e.Location);
if (info.InRow && !SearchResultGridView.IsGroupRow(info.RowHandle))
{
OnEditRecord(e);
}
}
Now the issue I am facing is every time I double click a row in grid view it calls the SearchResultListGridControl_MouseDoubleClick() which then calls OnEditRecord(), however the value of EditRecord is everytime null.
To solve this I checked the designer file of the Main Control which has SearchControl and could not find the EditRecord Event entry in this. So I manually created it like this:
this.MySearchControl.EditRecord += new performis.BA.Merkmalsleisten.Search.SearchControl.EditRecordEventHandle(this.MySearchControl_EditRecord);
Now the things are working fine, but my question is why it did not create it automatically at the first place? And as far I know it is not recommendable to add anything manually to the designer file..is there any other way I can do it?
Thanks

When you create event it has to be used in the form designer similar to how you are using MouseDoubleClick for the Grid (so you need to find event in the Misc category, because you didn't define CategoryAttribute, double clicked there, etc).
If I understand it right you want to subscribe to event automatically, when form is created. You can do this in the control constructor (find parent form control.Parent or control.FindForm()) or perhaps in the special method, which you have to call from the form constructor, which in turn is basically similar to wiring event manually (which you did in the designer created file, but, instead, you can do in the form file, which is totally ok to edit) Up to you.

Sure.
A better practice would be to add your binding line:
this.MySearchControl.EditRecord += new performis.BA.Merkmalsleisten.Search.SearchControl.EditRecordEventHandle(this.MySearchControl_EditRecord);
To the form's constructor. something like:
public MyForm()
{
this.MySearchControl.EditRecord += new performis.BA.Merkmalsleisten.Search.SearchControl.EditRecordEventHandle(this.MySearchControl_EditRecord);
//The rest of your constructor.
}

Related

How to force a certain Event sequence

I wrote a small control that creates a popup for my Win8 Phone application which does all the nasty things for me like rotation, proper placement etc.
The popup is opened in a Popup control but not on a new phone page.
To close the popup, my control hooks up to the "backKeyPressed" event of the underlying page.
This works like charm until the underlying page has its own implementation of BackKeyPressed event. In this case, the page event is triggered but not the popup control event.
If I would own the event, I could create my own stack to call the last added event first, but I do not own the event of the pages.
As far as I know, I am unable to unregister any previously attached event handler and reassign it once my control unsubscribes from the event.
I could have only one implementation for the BackKeyPressed event which then informs the popup control to close itself (if open), if nothing was open, do the Page specific implementation. But this would require code changes on all pages where I might want to use the popup. Even worse, if I have 5 possible popups, I would have to check all of them :-(
So I am looking for an option to handle this centrally.
What other options do I have to overcome this situation?
Normally you cannot change the order of fired events - they are executed in registered order, but it's not required by specifications - source.
But as Jon Skeet says here:
Summary: For all sane events, you can rely on the ordering. In theory, events can do what they like, but I've never seen an event which doesn't maintain the appropriate ordering.
it is fired in registered order and should be.
BUT for your purpose (I think) you can set an event to invoke your method where you would control the order. I think simple example can show this behaviour:
public partial class MainPage : PhoneApplicationPage
{
private List<EventHandler<CancelEventArgs>> listOfHandlers = new List<EventHandler<CancelEventArgs>>();
private void InvokingMethod(object sender, CancelEventArgs e)
{
for (int i = 0; i < listOfHandlers.Count; i++)
listOfHandlers[i](sender, e);
}
public event EventHandler<CancelEventArgs> myBackKeyEvent
{
add { listOfHandlers.Add(value); }
remove { listOfHandlers.Remove(value); }
}
public void AddToTop(EventHandler<CancelEventArgs> eventToAdd)
{
listOfHandlers.Insert(0, eventToAdd);
}
public MainPage()
{
InitializeComponent();
this.BackKeyPress += InvokingMethod;
myBackKeyEvent += (s, e) => { MessageBox.Show("Added first"); e.Cancel = true; };
AddToTop((s, e) => { MessageBox.Show("Added later"); });
}
}

How to sync up to different events in Winforms

If I have a button which does something and also a double-click event on a data grid which I want to do the same thing, what is the best way to ensure that only one function has to be maintained?
Apart from doing the following, is there any fancy C# way to indicate that two events are to do the same thing?
void button1_Click(...) { MyFunction(); }
void dataGrid1_DoubleClick(...) { MyFunction(); }
void MyFunction() { // do stuff }
I suppose that you are talking about a DataGridView (WinForms) so the signature of the event DoubleClick in the DataGridView and the signature of Click event on a button control is the same.
(An EventHadler). In this case you can simply set the same method using the form designer or manually bind the event
dataGridView1.DoubleClick += new EventHandler(MyFunction);
button1.Click += new EventHandler(MyFunction);
Of course the MyFunction method should match the expected signature of an EventHandler
private void MyFunction(object sender, EventArgs e)
{
// do your work
}
Reviewing my answer after a few minutes I wish to add:
If you find yourself in a situation in which you need to differentiate between the controls using the sender object (like Control c = sender as Control; if (c.Name == "someName") ) I really suggest you to return to the first idea. Call a common method but keep the EventHandler separated for each control involved.
Using VS, in the form's designer view You can set the procedure You want to call to each control's each event in the control's properties window.
image
Just to add to what Steve said, you will want to bind these events to your function manually in the Load event of your form, instead of using the events under the lightning bolt in the properties window in the designer, like so:
private void Form1_Load(object sender, EventArgs e)
{
button1.Click += MyMethod;
dataGridView1.DoubleClick += MyMethod;
}
void MyMethod(object sender, EventArgs e)
{
//Do Stuff
}
Also, declaring a new instance of the EventHandler class has been redundant since Anonymous methods were introduced to C#, you can just point the event directly at the method as shown above.

Update listBox on Main page from button click event on child window.

I have a Main page that contains a listBox.
When a user selects a profile form the list box, this opens up a child window called pWindow.
This window as the option to delete the current profile via a hyperlink button that opens up a another confirmation window called dprofile.
My question being is it possible that once a user has confirmed to delete the current profile they are in, and confirmed it in the button click on dProfile, how can I update the listBox in the first Main page so that the list no longer contains the deleted profile (which it is not doing at present.
In the dProfile window I have created an event -
public event EventHandler SubmitClicked;
Where in the OK button click I have-
private void OKButton_Click(object sender, RoutedEventArgs e)
{
if (SubmitClicked != null)
{
SubmitClicked(this, new EventArgs());
}
}
So on the Main page I have added-
private void deleteProfile_SubmitClicked(object sender, EventArgs e)
{
WebService.Service1SoapClient client = new WebService.Service1SoapClient();
listBox1.Items.Clear();
client.profileListCompleted += new EventHandler<profileListCompletedEventArgs>(client_profileListCompleted);
client.profileListAsync(ID);
}
I thought this may have updated the listBox as it was confirmed in the dProfile form however when the form closes, the listBox stays the same and I have to manually refresh the webpage to see the update. How can I do this?
If I understood it correctly then you have three pages. Main, pWindow and dProfile. Earlier you were trying to close pWindwow from dProfile and that was working properly. Now you want to refresh the listBox1 on Main Page.
To achieve that you may follow a similar strategy. You are probably opening pWindow from Main page with something on the following line
pWindow pWin = new pWindow();
pWin.Show();
Now you may define a new event in pWindow class.
public event EventHandler pWindowRefeshListBox;
Then in your event handler for deleteProfile_SubmitClicked you may raise the event to refresh listbox1, something on the following line:
private void deleteProfile_SubmitClicked(object sender, EventArgs e)
{
if(pWindowRefreshListBox != null)
pWindowRefreshListBox(this, new EventArgs());
this.Close();
}
Then in your main page register the event against pWin object, which you defined earlier.
pWin.pWindowRefreshListBox += new new EventHandler(pWindow_pWindowRefreshListBox);
Then define the event in Main page.
private void pWindow_pWindowRefreshListBox(object sender, EventArgs e)
{
listBox1.Items.Clear();
}
This should refresh the listbox. I haven't test the code or the syntax. So you may check it
before implementing.
EDIT
you may define the event in dProfile as static
public static event EventHandler SubmitClicked;
Then you will be able to register it in Main and pWindow against Class Name
dProfile.SubmitClicked += new ..............
Then implement it accordingly, in pWindow, close the window and in main refresh listbox
EDIT:
You may create instance of deleteProfile on the main page register the following in your main
deleteProfile.SubmitClicked += new EventHandler(deleteProfile _SubmitClicked)
this should work

Hooking up generic event handlers to multiple controls of the same type

I have a WinForms app that contains many NumericUpDown controls. In a nutshell, if my users enter a value into the control and then delete the text, I want to restore it (the text) when the control loses focus. So I decided that I'd check .Text when the control loses focus and if it's empty, I set .Text = .Value.ToString().
I'm doing this in the Leave event handler and it works just fine. But as I said, I have many of these controls (18, to be exact). I don't like creating 18 Leave event handlers that all do the same thing so I created a generic one like this:
private void numericUpDown_GenericLeave(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(((NumericUpDown)sender).Text))
((NumericUpDown)sender).Text = ((NumericUpDown)sender).Value.ToString();
}
I started to hook up all of the controls to this generic event handler but I quickly got tired of doing this:
numericUpDown1.Leave += numericUpDown_GenericLeave;
numericUpDown2.Leave += numericUpDown_GenericLeave;
numericUpDown3.Leave += numericUpDown_GenericLeave;
...
numericUpDown18.Leave += numericUpDown_GenericLeave;
So I thought I'd create a function that would return a list of all the controls of a specified type and then loop through that list and hookup the event handlers. That function looks like this:
public static List<Control> GetControlsOfSpecificType(Control container, Type type)
{
var controls = new List<Control>();
foreach (Control ctrl in container.Controls)
{
if (ctrl.GetType() == type)
controls.Add(ctrl);
controls.AddRange(GetControlsOfSpecificType(ctrl, type));
}
return controls;
}
I call the function like this:
var listOfControls = GetControlsOfSpecificType(this, typeof(NumericUpDown));
foreach (var numericUpDownControl in listOfControls)
{
numericUpDownControl.Leave += numericUpDown_GenericLeave;
}
When I run my app, however, I don't see the expected behavior that occurs when I manually hookup each control to the generic event handler. This code is currently in the constructor of my form and I've tried calling it before as well as after the call to InitializeComponent() but neither one seems to be working. I get no error of any kind, I just don't see the behavior that I was expecting. I have a breakpoint set inside the generic event handler but the debugger never breaks so it seems like the event handler isn't being hooked up correctly. Does anyone know why this might be or how I can troubleshoot it further? Thanks!
EDIT
I just realized that the call to:
var listOfControls = GetControlsOfSpecificType(this, typeof(NumericUpDown));
was happening before the call to InitializeComponent() so of course the list of controls being returned was empty. DOH! Thanks for all the replys. I apologize for wasting everyones time. :-(
You're passing this to your method, which is presumably a reference to your form. Your method will only catch the controls that are placed directly on your form. Any NumericUpDown controls that are not directly on the form (i.e. they're sitting on a panel or something) will be missed.
Why not create a user control that has a NumericUpDown control in it.
Then handle this is in the user control events.
This worked for me:
private decimal _previous = 0;
private void numericUpDown1_ValueChanged(object sender, EventArgs e)
{
if (((NumericUpDown)sender).Text.Length > 0)
{
_previous = this.numericUpDown1.Value;
}
}
private void UserControl1_Leave(object sender, EventArgs e)
{
if (this.numericUpDown1.Text == "")
{
this.numericUpDown1.Value = _previous;
this.numericUpDown1.Text = System.Convert.ToString(_previous);
}
}
Just note that the Leave event is on the user control not on the updown control itself.
Question answered. See Edit above. Thanks to bsegraves for pointing me in the right direction.

How to perform automatic button click on Windows Form based on a Parameter? C#

I created a Windows Application with a form and few buttons on it. I need to fire the button click event automatically some times based on the parameter value passed to the application.
static class SensexPrediction
{
static void Main(string[] Args) <---- Modified this so accepting arguments.
{
Application.Run(new Sensex_Prediction_Form(Args)); <--- Passing Args to Form.
}
}
Below is the Code for Sensex_Prediction_Form method.
public Sensex_Prediction_Form(String[] Args)
{
InitializeComponent();
if (Args.Length != 0) //There is atleast one argument.
{
this.Invoker = Args[0]; <-----Invoker is the name of the data member of the class.
}
}
Now on form load if Invoker == "X" i need to perform button1_Click event code. For that i wrote the following...
private void Sensex_Prediction_Form_Load(object sender, EventArgs e)
{
if(Inovker == "x")
{
predict_butn.performclick();
}
}
But click is not happening automatically even though argument passed is X.
What i couldn't understand is the button name in the solution explorer is predict_butn but when i click on the button the event code is in a function named button1_click. Is this the reason?
Please help. Thanks.
After the suggestions i separated the event code and actual logic in a separate method named prediction.
private void Sensex_Prediction_Form_Load(object sender, EventArgs e)
{
if (Invoker == "Scheduler")
{
prediction();
}
}
And i initialized the data variable of the class with Scheduler as below..
public string Invoker = "Scheduler";
Even then when i load the form the method is not being invoked.
As suggested i corrected the connection between button name and even method name etc.
thank q
Suprisingly..(for me :-))
if (Invoker == "Scheduler")
{
MessageBox.Show("Testing");
prediction();
MessageBox.Show("OK");
}
Testing message is getting executed but after that it just displays the form. so what could be the reason?
Understood the issue..I am getting an exception object reference not set..because i have a line that says
ActiveForm.Text = "Sensex Prediction System ";
At this point form has not been loaded so it can't set the text.
------> Now the issue is how to call a method automatically after loading the form? because the method will have code that will modify the form while executing.
Got it...using the "shown" event for the form able to do what i wanted. Thanks.
Promote the code within button1_click to a method. Then once the form is loaded and if the parameter match your filter, call the method.
private void Button1_Click(object sender, EventArgs e)
{
DoSomething();
}
private void Sensex_Prediction_Form_Load(object sender, EventArgs e)
{
if(Inovker == "X")
{
DoSomething();
}
}
private void DoSomething()
{
...
}
Extract the code out of the button event into it's own method that is called in the button click. Now you just need to call that new extracted method instead of trying to invoke a ui button click.
First you can use Environment.GetCommandLineArgs() instead of passing the args to the constructor of the form.
Second you may assign the wrong event handler to the click. reassign the predict_butn.Click to its correct event handler instead of the current one which is button1_click
Double click button to generate event handler(for example button1_Click(object sender, System.EventArgs e)), and then you want to trigger that method just call button1_Click(null, null)
Of course better solution is to create one function with your logic and then call that function in button click event and when Invoker == "X".
First of all, you're not checking whether Invoker == 'X', but Invoker == 'x'. This may be part of the problem. Comparing strings with == is not good practice, however. You should use
if (Invoker.Equals('X', StringComparison.InvariantCulture))
Is the action performed if you click the button with your mouse? If so, the problem is not the event handler.
If it is not performed, the event handler and the button's event are not connected. You can check in the button's properties whether the event handler is attached to the button's click event.
What happens if you double-click the button in the designer? Is a new event handler created? If so, move the code from button1_click to the new event handler and delete the button1_click event handler.
Event handlers and control events are not automatically associated. You need to do this in the control's properties.

Categories