C#, fire event of container
I have a MyButton class that inherits from Button. On this class I have placed several other controls (Labels, Progessbar). The problem with this is that the controls on the Button make it开发者_如何学C impossible to fire the Button.Click or Button.MouseHover event. How can I achieve it that the controls on the Button are only displayed but are "event transparent": A click/hover on the label and progessbar is the same as if I clicked/hover directly on the Button (including sender and everything). Something like "inheriting the events from the parent".
class MyButton : Button
{
Label foo = new Label();
ProgressBar bar = new ProgessBar();
}
You should derive from UserControl then have the button as a child control, and bubble up the button child's on click event.
This link is probably more than what you need, but it's a good starting point.
UPDATE
As pointed out, you may not be using ASP.NET. So here is another post that talks about different custom user controls, specifically what you're after is a Composite Control
. This is for Windows Forms.
Write Click event handlers for the label and PB, have them call PerformClick().
Making controls transparent to the mouse is possible but is ugly to do. You'd have to override WndProc() to catch WM_NCHITTEST and return HTTRANSPARENT. The all-around better solution is to not use controls. A Label is just TextRenderer.DrawText() in the button's Paint event. ProgressBar isn't hard either, e.Graphics.FillRectangle().
Having the child controls be real controls in front of the button (either in a class inheriting from Button
or from UserControl
) may make it hard to get button-specific events working properly, as you have found. (Edit: Although it's hard, it's not impossible -- see Hans Passant's answer)
As a workaround, instead of using child controls, you could custom-paint them onto the button surface, since you don't need most of the functionality of the controls (events, focusing, etc.), just their display.
You can do the additional painting in the OnPaint
method of your class. Something like:
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
e.Graphics.DrawString("My fake label", Font,
SystemBrushes.ControlText, new Point(10, 10))
// draw progressbar
}
To update the display, you would need to trigger a repaint of the Button using Invalidate()
.
Take a look at Custom Bitmap Button Using C# on CodeProject for a more complete example.
This answer was here a moment ago, but got deleted:
Can you inherit from UserControl
instead? This will allow you to place other controls on the control surface, including your button and subscribe to their events.
If you're using WPF, I guess what you're looking for would be something called Bubbled Events. It's a feature in WPF by which events are bubbled from a control to its parent (in your case, it would be from your ProgressBar and Label to your button). I found this article on the matter which I think would be of help to you.
Hope this helps :)
精彩评论