Charles Jenkins a écrit :
On 2006-08-21 10:38:52 -0400, Mathieu Cartoixa
<mathieu.cartoi xa@_NO_hotmail_ SPAM_.comsaid:
> Have you checked the method MenuItem.Perfor mClick in MSDN ?...
I am using the .NET Compact Framework, which seems to be designed for
frustration, becaue the method you NEED is never available. For
instance, MenuItem.Perfor mClick() does not exist in the Compact Framework.
I must admit I never used the Compact Framework. PerformClick seems to
be available for buttons, but not for menu items in this world :-(
<snip>
Because the VS 2005 designer is not reliable for custom controls, I am
trying to put plain old controls (with no visual inheritance) onto my
forms, then add the behaviors I need at runtime. I need
ClickableMenuIt em to inherit from MenuItem so that it can call
OnClick(); but I need each new ClickableMenuIt em to get its state from
the MenuItem that is actually available. I want to be able to do
something like this:
// Use what we have to create what we actually need
ClickableMenuIt em cmi = new ClickableMenuIt em( menuItem );
cmi.DoClick();
Well, except with Delphi, I have always been disappointed with
designers. The code they ususally produce is such a mess that they end
up being unable to deal with it after a while...
> * isolate your ClickableMenuIt em in a library and add it to the
designer controls. Use inheritance. The constructor would have no
parameters, and you could use it exactly like a MenuItem.
I think this would require the kind of inheritance that would lead me to
have problems with the designer. In order to add ClickableMenuIt ems
using the designer, I would have to create a ClickableContex tMenu, right?
I do not think so, as with inheritance a ClickableMenuIt em would be a
MenuItem. That reminds me of a hack I have used with VS2003 that should
work with VS2005 : add a MenuItem to your menu vie the designer, save
your files, close the designer, and replace MenuItem with
ClickableMenuIt em directly in the source code for your instance (ther
should be only two occurrences : one in the variable declaration, one in
the method InitializeCompo nents). Reopen the designer : you are done !
>
> * create your ClickableMenuIt em elements "by hand" in your form
constructor, after the call to InitializeCompo nents(). Use
inheritance. You would not want any parameter in your constructor either.
* let the designer create your MenuItem. Then create your
ClickableMenuI tem elements "by hand" in your form constructor, after
the call to InitializeCompo nents(). Use composition (which in this
case seems to be a rather long and fastidious if you do it properly...).
These workarounds still require me to make the ClickableMenuIt em to get
its state (fields and event handlers) from the MenuItem I want to
impersonate. That leads me back to this question. Given that I cannot
say "this = that," how do I copy all the MenuItem's fields and events
from the MenuItem I have into the ClickableMenuIt em that I want?
The first method uses inheritance : you are just not using the designer
for your specific components.
>
Oddly enough, I really *did* attempt to combine inheritance and
composition, just like you guessed, in the hope that an inherited
control could gain access to the protected methods of the member
control's instance---
class ClickableMenuIt em : MenuItem {
private MenuItem m_mi;
public ClickableMenuIt em( MenuItem mi ) {
m_mi = mi;
}
public void DoClick( EventArgs e ) {
m_mi.OnClick( e );
}
}
I have been there before : no matter what you are trying to achieve,
inheritance cannot live with composition (wit the same class involved,
of course ;-). It is always wrong.
But here is your real point : how to simulate the click ? Be careful
that OnClick just triggers the handlers registered to the Click event,
it does not perform any MenuItem specific action associated with the
click... The best solution if you want to call OnClick anyway is to use
inheritance and just :
public void PerformClick() {
this.OnClick(ne w EventArgs());
}
What if OnClick is not enough ?... I would try to use a reflector to
look deep into the MenuItem class (you can find one there :
http://www.aisto.com/roeder/dotnet/), and look for a private method that
would look like a PerformClick. Then I would call it using reflection,
which is a secret way to bypass the laws of method accessibility
(beuaark)...
Last thougt : I think that if you really had separated UI code from the
rest, you would not have felt this need to call a method that does not
exist... Let me explain that : what I think you did is something that is
very usual thanks to designers, I mean add a handler to your MenuItem,
and perform your actual actions in there
public void MyForm_myMenuIt em_Click(object sender, EventArgs e) {
// related actions...
}
So now you will want to programmaticall y click the myMenuItem to
perform the actions... Try instead to separate the code related to your
actions in another layer (most likely in another class)
public void RelatedActions( )
{
// some code here
}
and just replace the preceding with :
public void MyForm_myMenuIt em_Click(object sender, EventArgs e) {
RelatedActions( );
}
Now, can you not try to call RelatedActions directly instead of trying
to click the menu ?
>
Of course, that does not work. I can call OnClick() in my own instance
(where it would do no good) but not in m_mi (which has the handlers I
want to fire). That approach would have been wrong and very wasteful,
but if it had worked, I could have lived with it.
Have a great day, and thanks!