I am creating a custom control. Let's say I'm reinventing the wheel and creating a custom Button control that derives from the UserControl class(only for example)
Well, it of course has a Click event handler. Now my problem is, when do I call this event handler? I know it happens sometime between the Pages OnLoad and OnLoadComplete, but I'm not quite sure what event I can hookup to so that the Click event is raised at the same time as other control events.
When are you suppose to call custom control events?
In general you should raise the event as soon as you know that the underlying event has happened.
For example, how does the ASP.NET Button control know that the it was clicked by the use? It implements IPostBackEventHandler and the RaisePostBackEvent() method. That method will get called if there is postback event data associated with the control. I believe the association is determined by the "name" attribute that it renders. In RaisePostBackEvent() it then raises the Click event.
The question you need to answer is: How does your control know that it should raise its event? Once you find that our the rest is easy.
If your control has similarities to existing ASP.NET controls I would recommend stepping through the ASP.NET source code and seeing how those controls work.
If you implement IPostbackEventHandler, you can do something like this, taken from decompiling System.Web.Ui.WebControls.Button
protected virtual void RaisePostBackEvent(string eventArgument)
{
base.ValidateEvent(this.UniqueID, eventArgument);
if (this.CausesValidation)
{
this.Page.Validate(this.ValidationGroup);
}
this.OnClick(EventArgs.Empty);
this.OnCommand(new CommandEventArgs(this.CommandName, this.CommandArgument));
}
Related
I have a user control which is not declared in the designer. I have a button that I want to have create this user control when I click it - it should initialize the user control and insert it in the main UI.
However, it happens that the user control has a key press event on it, which is not firing.
Why does this happen?
I already tried to attach the event on the user control itself but it seems that it's not firing at all. Is there some kind of bug?
It is very hard to fix problems with code that you can't see, but in WPF, there are often reasons why Bubbling events like the KeyDown event don't fire. Occasionally certain controls may make use of these events and set them as handled internally, thereby stopping them from bubbling up any further.
The normal solution on these occasions is to use the related Tunneling events instead, which are raised before the Bubbling methods and not used internally by controls. So, while I can't guarantee that this will fix your problem, it is certainly worth trying to handle the UIElement.PreviewKeyUp event instead of the UIElement.KeyUp event.
... when the custom control includes a slider which has alsready a valuechanged event : seems the form that contains the custom control never receives that event, I have to change it to another name.
Is there a way to circumvent this: seems rather stupid that I have a valuechanged name for a custom control.
A ValueChanged event declared in bite the spider control and your custom control will not be in conflict. They will belong to two different instances.
Now, the custom event will not fire automatically, even though the slider event fires. You will have to add an event handler, internal to the custom control, handling the slider event. The handler should raise the custom event, this propagating the slider event to the container.
I could solve my problem by the tutorial of MSDN (http://msdn.microsoft.com/en-us/library/w369ty8x.aspx). I found out that because of previous considerations, my event publisher class called ButtonMenu was a singleton, which is no more needed. So, I modified it to a normal control class. I added all what is said in the MSDN site, and it worked properly!
How to get the value of usercontrol to page holding usercontrol?
If I understand correctly, the problem is that you are trying to access the user control's StudentId property in page_load of the page that hosts the user control?
If that's the case, it is quite likely that you are just trying to read the data before the user control has fired the SelectedIndexChanged event on the dropdown list.
The simplest solution is to move the code that reads the property to the Page_PreRender event. This event happens late in the page life-cycle, and after all the user events have had a chance to fire off.
As an alternative, you can expose your own event (I'll call it "UserControlDropDownChanged") in the user control and have the code in your SelectedIndexChanged event handler fire the user control's UserControlDropDownChanged event. In your page, during page_load or page_init you'd register an event handler to listen to UserControlDropDownChanged from the user control... and in that event handler perform whatever functions you need to when the drop down list's value changes.
I provided an example of how to use events this way in response to another question here on SO if you aren't familiar with this technique.
You'll need to expose this value as a public property of the user control.
Say that I have a web user control that has several drop down lists in it. They are all set to AutoPostBack = true, BUT each SelectedIndexChanged event handler in my control will fire/chain the other SelectedIndexChanged handlers I have defined for the other DDLs. This means that when the user changes a single DDL, the event handlers are chained/fired for several other DDLs. The logic for which events are chained is very complicated, data driven, and can change depending on which list was actually changed by the user. Therefore, it is very difficult to determine which event handler would fire last.
From the page's point of view, I want to subscribe to a single SelectionChanged Event on the user control that will only fire one time per postback and not until all of the event handlers have fired. I don't care which event handlers have fired, only that the state of the control as a whole has changed.
I'm using C# 3.5/ASP.NET 2.0/VisualStudio 2008
How can I go about doing this?
EDIT: Moved clarification into original description. I think the fact that I specified AutoPostBack=true without specifying that chaining was happening was misleading. I apologize for the confusion.
It depends on when you need the event handler to fire in the page lifecycle.
Here's one strategy:
1) In your user control, track the selection changing of your dropdown lists. If the event handler is executed, update your local tracking variables.
2) In your usercontrol's PreRender handler, check your tracking variables and if called for, fire the user control's SelectionChangedEvent.
This strategy will guarantee that the event handling phase of the page lifecycle is done, but has the drawback that your main page won't receive the "SelectionChanged" on your user control until the PreRender phase. This may or may not work for your situation.
If you need to handle the SelectionChanged event for your usercontrol earlier, then you will likely have to put in more complicated tracking logic in your dropdownlist handlers, and add a tracking variable to ensure that the usercontrol's "SelectionChanged" event only ever gets fired once.
I think you need to create a delgate in child control and then reference that delegate into parent control.
By Using reflector you can see that WPF UserControl is overriding AdjustBranchSource.
internal override void AdjustBranchSource(RoutedEventArgs e)
{
e.Source = this;
}
My very own problem regards inconsistency caused by that issue.
When an element is based inside a user control or outside. The Source parameter behaves differently. Which surprises me the source should always be the element in target by the RoutedEvent.
The question is why was it implemented like that?
This kinda makes sense. If you treat the UserControl as a black box then you shouldn't know what controls are on it, and thus the source of an event.
If you need to distinguish between different buttons on the UserControl then the UserControl should have it's own events which the buttons trigger. That way from the outside it looks like the right event and the user of the UserControl doesn't need to know which button did which event.
To give an example, on a listbox, do you need to know that the down-scroll button was the button that sent the original event? Or do you just need to know that a scroll-down event was triggered.
The source of a routed event can change throughout the routing of the event. I'm not entirely sure why UserControl changes it, but can you not just use the OriginalSource property on RoutedEventArgs instead?