Click here to Skip to main content
15,880,608 members
Please Sign up or sign in to vote.
4.00/5 (1 vote)
See more:
I have a PropertyGrid on form, and hook the 'MouseClick' event on, but, when I click on PropertyGrid, there is no any response(event) is invoked, ie, the 'MouseClick' event fails.

Plus, I try to write the following lines :

C#
foreach (Control c in propertyGrid1.Controls)
{   c.MouseClick += new MouseEventHandler(MyMouseClickEven);   }


It is intended to hook each Property with dedicated 'MouseClick' event, however, the line of 'propertyGrid.Controls' is not existed, but, I see there are 'ControlAdded' and 'ControlRemoved' attributes, why there is no propertyGrid.Controls ? Can someone provide the root cause ?
Posted
Updated 28-Jan-11 12:27pm
v2

The answer is simple. The controls you click when working with PropertyGrid are not those exposed via Control.Controls. You do not have direct access to "real" edit controls shown by PropertyGrid — for a good reason.

The control PropertyGrid is very special; it is very flexible, but methods of altering its behavior are very different. I found the description of this functionality in standard Microsoft documentation (for .NET Framework v. 2.0, long time ago). I don't see a reason to explain them (this is not easy) before you provide really good explanation of your goal. For now, I answered you question in full, because you just asked about a "root cause".

—SA
 
Share this answer
 
v5
Comments
Sports Kuo 28-Jan-11 2:32am    
=========================================
Thanks of your response.
Yes, I'll show my goal below for reference.

My goal is to edit a property which has a text (string[]) type, I would not use the system built_in function to edit/see it (when mouse hover on the property, it will show a read-only text window), instead I would detect the click on this property (with text), and show a specific edit form for user to edit it esily.
Is this idea feasible ? Or, there is other way easily to reach ?

Plus, I suppose, with this way, I may can do many other specific function.
Sergey Alexandrovich Kryukov 28-Jan-11 13:07pm    
I might need to dig in my old code. I used to develop very robust but not absolutely universal solution (or universal but based on my assumptions of the target structures and requirements for control/presentation).

Here is the idea. I find it nearly impossible to invoke your own edit control. Instead, the component provides a way to define your own editor to be embedded in the grid at the moment you edit a field. This is based on the attribute, and, like many similar things in WinForms, suffer from the specific problems of the ill-designed Component Model. In other words, there is no compile time control over validity of your editor, so you're bound to extra care and extra testing. Again, give me some time to look in my old code so I could point out required techniques. In the mean time you could find them in stadard Microsoft help.

--SA
Sports Kuo 30-Jan-11 21:01pm    
===========================================
Thank SA so much of your fully support !
I originally suppose it should be very simple to reach my goal as usual (such as TreeView control), however, for PropertyGrid, it seems be a big job to reach my goal, I'll study your excellent description(article), hope I can do it in success. Thanks again, and I believe I'll see you again due to my next questionsss...
=========================================
Sergey Alexandrovich Kryukov 30-Jan-11 21:18pm    
Thank you Sports,
I think you can follow my second answer, because you have all the critical points of the API to pay attention for, then you can find the rest in documentation. However, you will need to work pretty hard to put all together. If I forgot any subtle moments, you'll likely face them, too, but in this case you can ask a question, most likely I'll have the answer.

I think you have to accept both my answers for now because I think the answer both your original and follow-up question (in case you haven't done this yet). Also, consider to vote.

Thank you and good luck.
--SA
Sports Kuo 15-Mar-11 7:08am    
===========================================
Hi SA, see you again.
I try to write a sample code to show a PropertyGrid with just two properties, one is normal type 'int', the other is 'string' type which I would assign specific multiple line editor, and I implement the rule as your guideline, however, there are several questions beyond my understanding, may I ask to discuss those questions through my mail sportskuo@yahoo.com.tw and yours ?
Thanks again of your kind help.
All right, here is a separate answer to a follow-up question by Sports Kuo: how to customize the editing of the fields of the target structure used to be edited by System.Windows.Forms.PropertyGrid using its property SelectedObject.
As I say (please see my comments to my other answer), this component is not designed to intercept events and replace in-place editor with a custom editor.

The technique is so complex that it would take a whole big article to explain the techniques. As I'm not writing such article, I can only depict the steps schematically; and the detail should be taken from regular Microsoft help.

So, the design System.Windows.Forms.PropertyGrid suggests to modify in-place editor by sub-classing. More than that, to invoke such editor, the property SelectedObject should not be used with the target object. Instead, that object should be dynamically wrapped in some class implemented the interface System.ComponentModel.ICustomTypeDescriptor. Let's name this class "PropertySurrogate". Let's also assume the surrogate (wrapper) takes an actual object as a constructor parameter: PropertySurrogate.PropertySurrogate(object target). When this is done, the surrogate should be used instead of actual target object:

C#
System.Windows.Forms.PropertyGrid myPropertyGrid;
object selectedObject = //object of any type usually class or structure

//...

//default behavior:
myPropertyGrid.SelectedObject = selectedObject;

//custom behavior: using custom editor(s) and more:
myPropertyGrid.SelectedObject = new PropertySurrogate(selectedObject);

//...

Note: PropertyGrid itself is not modified. It is the PropertySurrogate defines all the detail of the presentation of selectedObject: which members to show, which members are allowed to be editable and the editors. Also, nested structures could be shown in a special way, using miniature tree views (see for example, how the properties of the type System.Graphics.Point are presented; same effect can be achieved for any other structure).

Now, as System.ComponentModel.ICustomTypeDescriptor should be implemented. All 12 of the interface methods are important, one of the interface methods is used to define the editor: System.ComponentModel.ICustomTypeDescriptor.GetEditor. The interface can be implemented using the "helper" class System.ComponentModel.TypeDescriptor, but the particular implementation which need to select some specialized kind of editor should provide special editor instead the default.

Here is my example. I had to implement text-property editor in addition to the default string editor. The default editor behaves like single-line edit control, but I needed a multi-line text editor. First of all, I need to specify which properties "deserve" multi-line editing. For this purpose, I created a special attribute:

C#
[System.AttributeUsage(
    System.AttributeTargets.Property,
    AllowMultiple=false, Inherited=false)]
public class UiMultilineTextAttribute : System.Attribute { }


Using Reflection, we need to look at every property of the target object type, find out what editor should be used (if any) and pass this information to implementation of System.ComponentModel.ICustomTypeDescriptor.GetEditor. This implementation should also use the editor type, so it ultimately brings us to the editor itself.

To implement the editor good for the use by PropertyGrid via the class implementing System.ComponentModel.ICustomTypeDescriptor, one should create a class using the type System.Drawing.Design.UITypeEditor as a base class:

C#
internal class MultilineStringEditor : UITypeEditor {
    //...
    public override UITypeEditorEditStyle GetEditStyle(
        ITypeDescriptorContext context) { /*...*/ }
    public override object EditValue(ITypeDescriptorContext context,
        IServiceProvider provider, object value) { /*...*/ }
    TextBox TextBox = new TextBox();
    //...
} //MultilineStringEditor


Here is a way to insert some control in the editor:

C#
IWindowsFormsEditorService edSvc =
    (IWindowsFormsEditorService)provider.GetService(
         typeof(IWindowsFormsEditorService));
//...
//... make string from object, assign to TextBox.Text
//... set up TextBox properties
//embed TextBox into the PropertyGrid in the drop-down form:
edSvc.DropDownControl(TextBox);


In the implementation of MultilineStringEditor the instance of the TextBox should be re-used using lazy evaluation technique: one needs an instance of the text box and an activation flag as the slot of the class MultilineStringEditor. All the activation should be done only once per the instance of the class.

In this way, I implemented special editors with few field in one editor to edit Multiplicity, another special string editor to edit file names (showing ellipsis button calling a regular File Fialog and more. The special chapter is editing enumeration-type members. This is a whole big topic.

For a complete course on my enumeration techniques please see my series of three CodeProject articles on Enumeration topics, please find them in my CodeProject profile.

How's that?

Thank you.
—SA
 
Share this answer
 
v5
Comments
Espen Harlinn 29-Jan-11 3:42am    
Well, another 5+ rated answer :)
Sergey Alexandrovich Kryukov 30-Jan-11 14:23pm    
Thank you very much, Espen.

This is yet another good idea for an article, and a pretty big one.

Also, this is a good matter to criticize Component Model Microsoft used extensively for Forms.

Finally -- remember our discussion on Meta-classes? -- when I worked on implementation, I figured out that the lack of fully-fledged meta-classes (following Delphi-style RTTI) spoils all the flexibility, more exactly, allows to achieve flexibility at the expense of compile-time validation, hence at the expense of reliability and robustness of the development technique.

--SA
Espen Harlinn 30-Jan-11 14:32pm    
Depending on perspective - you'll find that much of the facilities of the MOF are available - but you'll have to consider the capabilities found in the System.ComponentModel, System.Reflection and System.Reflection.Emit namespaces. .Net allows you to implement dynamically typed elements that integrate well with the standard methods used by components to expose properties to designers and other tools using the approach you have partially outlined above.
Sergey Alexandrovich Kryukov 30-Jan-11 19:01pm    
Espen, that does not provide excuses for certain sloppiness I can see in Component Model classes and their uses in Forms. How about the case when a valid method of a type attached for a class through an attribute is recognized by its name (instead of using an interface)? -- absolutely non-verifiable be the compiler. Perhaps, you need to know that exact cases I mean. It would need some more detail writing...

--SA

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900