I am making an asynchronous call to wcf service methods and generated a Completed event on Button click:
private void OnSearchProductClick(object sender, RoutedEventArgs e)
{
service.GetProductsCompleted += new EventHandler<GetProductsCompletedEventArgs>(webService_GetProductsCompleted);
ProductType productType = (ProductType)cboProductType.SelectedItem;
_productTypeID = productType.ProductTypeID;
service.GetProductsAsync(txtName.Text, txtCode.Text, _productTypeID);
}
Problem is, the webService_GetProductsCompleted event gets called multiple times. When click the Button for first time it gets called once, when I click second time gets called twice when click third time gets called thrice and so on. This is a very unusual behavior. Why is it happening and how can I resolve it?
Here is the webService_GetProductsCompleted event:
public void webService_GetProductsCompleted(object sender, CatalogueServiceReference.GetProductsCompletedEventArgs e)
{
if (e.Result.Count != 0)
{
PagedCollectionView pagingCollection = new PagedCollectionView(e.Result);
pgrProductGrids.Source = pagingCollection;
grdProductGrid.ItemsSource = pagingCollection;
pgrProductGrids.Visibility = Visibility.Visible;
}
}
The problem is this line:
service.GetProductsCompleted += new EventHandler<GetProductsCompletedEventArgs>(webService_GetProductsCompleted);
You should call it from the form Load event, not here. Because every time you call these methods (OnSearchProductClick) you add the same handler again so it gets executed multiple times.
Other option is un-register it first and then register it again.
problem is here.
private void OnSearchProductClick(object sender, RoutedEventArgs e)
{
service.GetProductsCompleted += new EventHandler<GetProductsCompletedEventArgs>(webService_GetProductsCompleted);
}
By doing this, you are subscribing event in click event, thus on every click you are making new subscription.
Instead of this, you should be subscribing service's event once (before this click event, usually in load event of form or in constructor as per your convince).
But one thing you should keep in mind, this "service" object should be the same while subscribing event and calling API.
following link may clear this idea
https://msdn.microsoft.com/en-us/library/ms366768.aspx
Related
The problem we are having is accessing the click event for a button which is created in the click event of another button i.e. clicking the first button generates a new panel and controls, and we now want the button on this newly created panel to perform an action.
The controls have been declared at the top of the class as follows:
Panel createElementPage = null;
TextBox elementDescription = null;
TextBox elementName = null;
Button continueButton = null;
AuditSystem audit;
Here is an excerpt of the method that generates the new panel, the part that defines the continueButton is written as follows:
public void CE_Click(object sender, EventArgs e)
{
createElementPage.Controls.Add(elementDescription);
continueButton = new Button();
continueButton.Text = "Continue";
continueButton.Location = new Point(700, 500);
continueButton.Size = new Size(100, 50);
createElementPage.Controls.Add(continueButton);
}
We want to access the continueButton's click event handler but the method we have written does not seem to be working. This is what we have so far:
private void continueButton_Click(object sender, EventArgs e)
{
Console.WriteLine(" something");
}
Clicking the button yields no results, and we have tried a few solutions such as implementing a seperate eventHandler method. Does anybody have a fix for this?
You have to actually subscribe to the event:
continueButton.Click += continueButton_Click;
Events need to be told what they should handle. Without that, they won't "listen" to anything.
Friendly note: be careful when adding handlers "on demand" like this (i.e. outside of the designer). It doesn't really apply here (you have a new button each time), but it's fairly easy to accidentally subscribe to a control's event multiple times, and your handler will fire multiple times as a result. It's just nice to be aware of :)
In our window base c# project. We use the pageinteractorcreater i call this function using page viewer delegate I use for that following code
but it works at the second time page load event, but we want to invoke it on menustrip item click.....
public Form1()
{
InitializeComponent();
//it works
pagesViewer1.ZoomMode = ZoomMode.FitPageWidth;
pagesViewer1.PageInteractorCreated += new
EventHandler<TallComponents.Interaction.WinForms.Events.InteractorEventArgs>
(pagesViewer1_PageInteractorCreated);
}
private void editTextToolStripMenuItem_Click(object sender, EventArgs e)
{
// it does not work
pagesViewer1.ZoomMode = ZoomMode.FitPageWidth;
pagesViewer1.PageInteractorCreated += new
EventHandler<TallComponents.Interaction.WinForms.Events.InteractorEventArgs>
(pagesViewer1_PageInteractorCreated);
}
It doesn't work mean it never raises the event. Use menu strip clicked event, instead of editTextToolStripMenuItem_Click. And create a method and put your code in it.
You can see the complete list of event here.
Heyo,
I have a standard WinForms MonthCalendar in my application with a handler hooked up to the DateChanged event. Whenever I change the date by day, clicking on a certain date in the little calendar, the event fires once. However, whenever I change the date by month, clicking on the < and > in the control, the event fires twice. I want the event to fire once in all situations.
Any ideas?
EDIT: I debugged and found out that the SelectedItem or Range is the same on the first and second handler call. So I need a way to differentiate between the first and second call while still allowing for proper handling when the event only fires once.
The handler code was requested, here it is, but it has nothing to do with the event firing multiple times:
List<TimestampInfo> displayTimestamps = databaseManger.QueryForTimestamps(DayPicker.SelectionRange);
if (displayTimestamps == null) return;
TimestampsListBox.Items.Clear();
TimestampsListBox.Items.AddRange(displayTimestamps.ToArray());
Somewhat of a hack, but compare the SelectionRange string value with the last DataChanged event. Just run your code if it's different:
private string _LastRange = string.Empty;
private void monthCalendar1_DateChanged(object sender, DateRangeEventArgs e) {
if (monthCalendar1.SelectionRange.ToString() != _LastRange) {
_LastRange = monthCalendar1.SelectionRange.ToString();
List<TimestampInfo> displayTimestamps = databaseManger.QueryForTimestamps(DayPicker.SelectionRange);
if (displayTimestamps == null) return;
TimestampsListBox.Items.Clear();
TimestampsListBox.Items.AddRange(displayTimestamps.ToArray());
}
}
I couldn't reproduce this until I hooked up the event handler twice.
monthCalendar1.DateChanged += new System.Windows.Forms.DateRangeEventHandler(this.monthCalendar1_DateChanged);
monthCalendar1.DateChanged += new System.Windows.Forms.DateRangeEventHandler(this.monthCalendar1_DateChanged);
Is you code munging around with the event handlers?
Try this:
private void monthCalendar1_DateChanged(object sender, DateRangeEventArgs e) {
Calendar1.SelectedDate = Calendar1.VisibleDate;
// any additional code optional
}
I have a webusercontrol with a few controls on it like some labels,a textbox and eventually a button. The purpose of this control is to add it to my main page in a placeholder every time I click on the button on the webusercontrol.
This is the code behind my button on my webcontrol
protected void btnCriteriaToevoegen_Click(object sender, EventArgs e)
{
//New eventhandler == all of the eventhandlers of all the objects who have subscribed to the event.
EventHandler eventhandler = ButtonDoorgaan;
ButtonOpslaanEvent mijnevent = new ButtonOpslaanEvent();
//Basic variables I will give with my costum event(ButtonOpslaanEvent)
mijnevent.Naam = txtCriteriumNaam.Text;
mijnevent.Score = Convert.ToInt16(DdlCriteriumScoreSchaal.SelectedValue);
int weging = Convert.ToInt16(DdlCriteriumWeging.SelectedValue) - 1;
mijnevent.Weging = Convert.ToInt16(weging);
//If the eventhandler is not null, for every object that has an eventhandler, execute it.
if(eventhandler!=null)
eventhandler(sender, mijnevent);
}
The eventhandler that need to be executed when the event is fired is defined in my main page like this :
private void critlijn_ButtonDoorgaan(object sender, EventArgs e)
{
ButtonOpslaanEvent eigenevent = (ButtonOpslaanEvent)e;
IEnumerator<Domein> domeinenumerator = domeinen.GetEnumerator();
while (domeinenumerator.MoveNext())
{
if (domeinenumerator.Current.DomeinNaam.Equals(lijstdomeinitemgeselecteerd))
{
Criterium nieuwcriterium = new Criterium();
nieuwcriterium.CriteriumNaam = eigenevent.Naam;
nieuwcriterium.CriteriumScore = Convert.ToString(eigenevent.Score);
nieuwcriterium.CriteriumWeging = Convert.ToString(eigenevent.Weging);
domeinenumerator.Current.Criteriums.Add(nieuwcriterium);
}
}
btnCriteriaToevoegen_Click(sender, e);
}
The btnCriteriaToevoegen_Click event fires and then calls this method(addCriteriaButton()), which will add the button onto the placeholder in my main page:
private void addCriteriaButton()
{
Criterialijn criterialijn = (Criterialijn)LoadControl("~/Criterialijn.ascx");
//Add eventhandlers to control
criterialijn.ButtonDoorgaan += new EventHandler(critlijn_ButtonDoorgaan);
criterialijn.Aangevinkt += new EventHandler(critlijn_Aangevinkt);
//Every control on the page except this one, not enabled
IEnumerator<Criterialijn> criterialijnenumerator = criteriacontrols.GetEnumerator();
while (criterialijnenumerator.MoveNext())
{
criterialijnenumerator.Current.Enabled = false;
}
//Add it to a list of webusercontrols that are currently on screen
criteriacontrols.Add(criterialijn);
criterialijn.Enabled = true;
//Add to placeholder
plhCriteria.Controls.Add(criterialijn);
}
So when all this is said and done, and I run my program, he adds the control to my placeholder, but when I click on the button, he does not add a new control to my placeholder, and just clears my placeholder for some reason. Normally everything should be fine, but I have tried to see if he actually fires the event when you click on the button, and he does not. I have tried to give you a sample of my code, because the code of the whole page is quite big and that would not help you at all. Any ideas why he is not firing the event of the button?
So when your button that you dynamically added posts back, a new page instance is created and that button no longer exists (since you only added it on the previous button click), it has not been recreated.
You must re-create dynamic controls on each postback
Remeber, a new instance of the Page class is created for each postback, any previously created controls, event handlers will not exists in the new instance unless you explicitly re-create them.
I assume these Criteria are some sort of tree structure the user can navigate through (and hopefully arriving at the end somewhere ?).
About btnCriteriaToevoegen_Click:
Why are you defining an event inside a method?
In critlijn_ButtonDoorgaan and addCriteriaButton:
Instead of using an enumerator, just use
foreach(var control in criteriacontrols)
control.Enabled = false;
So yeah, fair to say it's still not quite comprehensable, but it least I tried right? :)
EDIT
ok, then I have this question:
The eventhandler that need to be
executed when the event is fired is
defined in my main page like this :
How sure are you that, when you do
EventHandler eventhandler = ButtonDoorgaan;
the variable "eventhandler" gets all eventhandlers attached to ButtonDoorgaan ?
EDIT 2 (the return)
See Richard Friend's answer; your control is not there anymore
I am new to windows.forms programming. I started making an application that has the following flow of events:
click a button that opens a file - extract its contents in some list of strings - visit some websites - parse their content - etc.
So because everything in my app happens after i click a button to open a file, I have put all my code on the click event of the button. However I do know this is bad coding practice, because I realised I ended up having ALL the program flow inside that click event. I know that the event should only contain code related to the button, but where to place the code that follows, if not inside the event? Is there another event that I should use instead of just writing all in the button click?
I hope I've made my question clear. If not then I'll retry to explain my problem. I simply don't know where to write the code that follows the click event. If I put it in:
public Form1()
{
InitializeComponent();
}
..then it executes before the click event which is wrong.
Thank you in advance.
The typical way to do this is to write one or more methods that perform the action, and call those from the click event. For any long-running actions, do them in a background worker thread.
For example:
public void myButton_OnClick(EventArgs e, object sender)
{
VisitWebSites();
}
private void VisitWebSites()
{
var webSiteList = GetWebSitesFromFile();
foreach (var w in webSiteList) {
StartVisitingWebSite(w);
}
}
private IEnumerable<string> GetWebSitesFromFile()
{
// whatever
}
private void StartVisitingWebSite(string url)
{
backgroundWorker1.RunWorkerAsync(url);
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
string url = (string)e.Argument;
e.Result = VisitWebSite(url);
}
private string VisitWebSite(string url)
{
// This is called in background thread. Do whatever you do to return data.
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Error || e.Cancelled)
return;
string result = e.Result.ToString();
// Do whatever you do with the result
}
Look at the BackgroundWorker documentation to see how to perform actions in a background thread and then handle their results.
You can encapsulate all of the work that you want to do into another function in the form's class. Its modification access would be PRIVATE of course (unless you want another class to be able to access the method). From inside of your button_click event handler, you can call this new function. That is simplest way to do this. Otherwise, you can use the example provided in the link above by #Robert S.
You should look into the Model View Presenter pattern. http://msdn.microsoft.com/en-us/magazine/cc188690.aspx