Propagation of events from custom control to Form

R

Rob

When a custom control is used within a form, that control does not get
events directly. I've run into this a couple times with both mouse
and keyboard events.

Ex: A custom control inherits from UserControl (or Panel, etc). If
that particular control is being edited, it IS possible to assign
handlers and get events.

However, when the control is used on the main form, assigning a
handler to the particular control does nothing--the handler never
executes.

Rephrased: Using a ListView directly on a form == no problem.
CustomListView control has a ListView anchored to all sides. Drag it
to a form. Assign event handlers. Nothing.

This has to be something to do with the hierarchy of event
propagation, right? How is this normally handled?
 
M

Marc Gravell

What events specifically? Most events don't automatically propegate - they
are local to the source. If you want it to do this you need to handle it
yourself.

Marc
 
R

Rob

What events specifically?

Keyboard in this case. Previously ran across the same thing with Mouse
events.
Most events don't automatically propegate - they
are local to the source.

Every normal control handles its events at the expected place. I'm not
sure why this would be any different. Drag the custom control to the
form, use the properties editor on that screen to assign a KeyDown
handler. What could be more intuitive?
If you want it to do this you need to handle it yourself.

How is that?
 
M

Marc Gravell

The events you subscribe in the IDE are going to your UserControl / Control;
however, this will only fire events if it is the control receiving input.
For instance, a "Click" *can* get fired *if* you click on the grey area
between the child controls. Of course, if you have anchor / dock - filled,
then it can't get these inputs.

The trick here would either be for your child control to trigger the wrapper
control's events (by calling OnSomeEvent), or to expose passthru events
instead, e.g.

public EventHandler TextboxClicked {
add {textbox1.Click += value;}
remove {textbox1.Click -= value;}
}

Of course, this latter can be confusing as the "sender" is now textbox1, not
your (wrapper) control instance...

Marc
 
O

Olie

I am not sure exactly what you are asking but here are two possible
causes of the behaviour you mention.

Your user control contains other controls that have the keyboard focus.
These events will be passed to the UserControl but will not be passed
to the form unless you explicitly relay them on in code.

The form has KeyPreview set to true and are being flagged up as
handled. In this case the key press will never be passed on to any
other control.

The event will be handled somewhere you just need to find out where and
then route it through to the form.
 
R

rob

I am not sure exactly what you are asking but here are two possible
causes of the behaviour you mention.

Your user control contains other controls that have the keyboard focus.
These events will be passed to the UserControl but will not be passed
to the form unless you explicitly relay them on in code.

The form has KeyPreview set to true and are being flagged up as
handled. In this case the key press will never be passed on to any
other control.

The event will be handled somewhere you just need to find out where and
then route it through to the form.

To clarify:

class CustomControl : UserControl
{
ListView lv; // anchored to all four sides
}

Normally, when a ListView control is dropped onto a form, the control
on the form can be r-clicked, and its events can be wired into the
form's code.

You are correct that in this case, the event never gets that far, but
it is not due to KeyPreview--they just stop at the UserControl level.
Ideally, this custom control should generate events exactly like a
regular ListView.

So I've got to 'rethrow' keyboard events to make it appear that it was
generated by the custom control. And it should look just like a
regular KeyPress event to the client form. That is where I'm short on
info. Any references?
 
R

rob

The events you subscribe in the IDE are going to your UserControl / Control;
however, this will only fire events if it is the control receiving input.
For instance, a "Click" *can* get fired *if* you click on the grey area
between the child controls. Of course, if you have anchor / dock - filled,
then it can't get these inputs.

The trick here would either be for your child control to trigger the wrapper
control's events (by calling OnSomeEvent), or to expose passthru events
instead, e.g.

public EventHandler TextboxClicked {
add {textbox1.Click += value;}
remove {textbox1.Click -= value;}
}

Of course, this latter can be confusing as the "sender" is now textbox1, not
your (wrapper) control instance...

I was with you up to the last part. I did consider trying to find the
parent's 'OnKeyPressed' handler and connecting to that, but it does
not seem like the right approach.

When you refer to 'passthru events', do you mean there is a mechanism
in place for passing the ListView's KeyPressed events up through to
the client form? Easy enough to get them in the UserControl-based
container, of course, but the problem is how to regenerate them so it
looks like the UserControl is the source of the KeyPressed event. That
is what I'm looking for.
 
M

Marc Gravell

Nope; unfortunately the events are not marked as virtual, otherwise yes: you
could do this and simply hook into every sub-control. So if you want to use
the standard events, you must explicitely raise the OnEvents yourself...
AFAIK.

Marc
 
O

Olie

I think I have a better understanding of what you are trying to do. My
first question to you is why are you not inheritting from ListBox
rather than UserControl. If you wanted to construct your user control
from multiple controls then your approach is correct. If you inherit
from ListBox then you will not have to worry about re-routting the
events.

Going back to what you are trying to do. I think this is where you are
getting confused but I am not sure.

When you drop a control on a UserControl the events for that control
will need to be handled in the UserControl Code. So you add a list box
to the control and it will fire an event in the UserControl. If you
then do not handle it the event will be lost. They do not get
propagated down to the form! There is a very good reason for this as it
allows you to control the events in your user control.

You need to handle the ListBox events in your UserControl and then
raise the event in your user control. This way the event will be passed
to the form.
 
R

rob

I think I have a better understanding of what you are trying to do. My
first question to you is why are you not inheritting from ListBox
rather than UserControl. If you wanted to construct your user control
from multiple controls then your approach is correct. If you inherit
from ListBox then you will not have to worry about re-routting the
events.

A week late in reply, sorry.

It's actually a ListView. I needed to set column defaults, etc for the
ListView, and it seemed that putting the listView in a UserControl
would be an easy way to do that.
You need to handle the ListBox events in your UserControl and then
raise the event in your user control. This way the event will be passed
to the form.

I have been able to do that with most events, but I haven't been able
to get item checkbox-clicked events back to the parent.

The problem could be solved by:
Getting checkbox-changed events to the parent form
or
Finding a convenient way to edit colummns and other parameters when
inheriting directly from ListView.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top