Click here to Skip to main content
15,898,374 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
Hi all,

How can i add something like "Items" property of ComboBox control to my propertygrid?

I mean i want to have a textbox with a browse button next to it as a property of propertygrid, that a form opens when the button will be clicked.

I have tried the solution suggested here, But the problem is that i do not want to have expandableObject.Infact i want to show the result of FooForm just in front of FooProperty not as the value of Bar property.
Posted
Comments
BillWoodruff 1-Oct-13 8:41am    
That's an interesting question.

How essential is it to you that the Label (text) of the GridItem which is the "gateway" to editing your collection actually shows the current selected value within the collection ?

In other words: if you have a collection of strings, BunchOfStrings, would it be okay to see in your PropertyGrid something like what you see now for the Lines collection of a TextBox: where you see the collection name, followed by the Type name, with the ellipsis character in an enclosing "box" at the far right ?

I understand (I think) that you don't want what the example you linked to shows, where the current selected value of the collection is displayed as a second GridItem which is a "child" of the 'Foo GridItem.

But, please clarify this a bit more: "i want to show the result of FooForm just in front of FooProperty not as the value of Bar property." What exactly do you mean by "result" ? Do you mean something other than the currently selected value in your collection ?
johannesnestler 2-Oct-13 16:59pm    
yes, i was thinking about his last setence too, anyway have a look at my answer if you are interested...
M_Mogharrabi 5-Oct-13 1:33am    
Thanks BillWoodruff for your reply. "What exactly do you mean by "result" ? Do you mean something other than the currently selected value in your collection ?"
No i mean exactly the selected value in my collection by "result".
BillWoodruff 2-Oct-13 23:14pm    
I suggest you take a look at: "How to incorporate ListBox in PropertyGridControl?" http://stackoverflow.com/questions/15131252/how-to-incorporate-listbox-in-propertygridcontrol

Hi M_Moghrabbi,

Have a look at this runnable example:
Hard to tell from your description if this is exactly what you want - but I think it's quite close:

using System;
using System.ComponentModel;
using System.Drawing.Design;
using System.Windows.Forms;
using System.Windows.Forms.Design;

namespace PropertyGridTest
{
    static class Program
    {
        class TestPropertyEditor : UITypeEditor
        {
            public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
            {
                return UITypeEditorEditStyle.Modal;
            }

            public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
            {
                IWindowsFormsEditorService editorservice = provider.GetService(typeof(IWindowsFormsEditorService)) as IWindowsFormsEditorService;
                if (editorservice != null)
                {
                    // Let's create a test dialog to select some strings
                    // - Replace this whith your selection dialog form and your objects
                    Form formDialog = new Form();
                    Button buttonOk = new Button { Text = "Ok", Dock = DockStyle.Bottom, DialogResult = System.Windows.Forms.DialogResult.OK, Parent = formDialog };
                    Button buttonCancel = new Button { Text = "Cancel", Dock = DockStyle.Bottom, DialogResult = System.Windows.Forms.DialogResult.Cancel, Parent = formDialog };
                    formDialog.CancelButton = buttonCancel;
                    formDialog.AcceptButton = buttonOk;
                    ListBox listbox = new ListBox { Dock = DockStyle.Fill, Parent = formDialog };
                    // Add some test items to select
                    listbox.Items.AddRange(new object[] { "Test1", "Test2", "Test3" });

                    // re-select current value
                    if (value != null)
                        listbox.SelectedItem = value;

                    // show the dialog
                    if (editorservice.ShowDialog(formDialog) == DialogResult.OK)
                    {
                        // set the selected object as new value (which is returned)
                        value = listbox.SelectedItem;
                    }

                }
                return value;
            }
        }

        class TestObject
        {
            // The Property with the special editor
            [Editor(typeof(TestPropertyEditor), typeof(UITypeEditor))]
            public string TestProperty { get; set; }
        }

        static void Main()
        {
            // Create a simple test Form with a PropertyGrid
            Form formMain = new Form();
            PropertyGrid pg = new PropertyGrid { Dock = DockStyle.Fill, Parent = formMain };
            pg.SelectedObject = new TestObject();

            Application.Run(formMain);
        }
    }
}


So I created a TestObject class representing the object type you show on your PropertyGrid. This class has one string property TestProperty - this represents the "TextBox" value in your PropertyGrid - but we set the Editor Attribute to our own editor (TestPropertyEditor). If you click on the button next to the (initally empty) property value, the dialog defined inside our Editor implementation will open and show a selection.

Does this code what you want? - if not feel free to ask for further help...

Kind regards

Johannes
 
Share this answer
 
Comments
BillWoodruff 2-Oct-13 21:27pm    
Hi Johannes, What an excellent response: got my #5 !

Since the OP hasn't responded to a request for clarification of what, exactly, they want, I think we're kind of guessing, but your code is a great resource: I wonder if the OP really wants to show a Form.

Looking at your code, I wonder if:

1. it might be good to add a Constructor to 'TestObject in which you instantiate and configure the FormDialog, and ListBox, the Buttons. I think if that business is done outside the TestPropertyEditor that's a good thing (separation of concerns).

1.a. my own preference would be to create a UserControl, and design it in advance, and make it visible as needed.

2. perhaps pass the instance of the PropertyGrid on a Form as a parameter to the Constructor of TestObject ? That way the TestObject Constructor can define a "local" PropertyValueChanged EventHandler for the PropertyGrid.

3. TestPropertyEditor does require access to the Form shown modally, and the ListBox: that could be handled any number of standard ways (static Public Properties defined in the TestObject Class and set in its Constructor, etc.).

4. In the case the end-user types a new value in the Property Tab, should it be added to the ListBox Items ? My intuition says it should, and that's where the use of the PropertyValueChanged Event would be useful, as in:

private void currentPropertyGrid_PropertyValueChanged(object s, PropertyValueChangedEventArgs e)
{
if (! theListBox.Items.Contains(e.ChangedItem.Value))
{
theListBox.Items.Add(e.ChangedItem.Value);
}
}

But, once you've done that, and added a facility in the Form to remove, or edit, the ListBox Items ... I think the development cost far exceeds just figuring out a way to have the ellipsis-in-box indicator open the kind of editor you see now for ComboBox Items in the PropertyGrid.

I assume, but am not sure, that's possible while still displaying some current value in the PropertyGrid.

Anyway, this OP was very lucky to have this response from you :)

edit: found this today which I think is very relevant for this type of UI problem:

http://stackoverflow.com/questions/15131252/how-to-incorporate-listbox-in-propertygridcontrol
johannesnestler 3-Oct-13 3:59am    
Hi Bill,

Thank you for your kind words.
I worked a lot in the past with designer support and of course the PropertyGrid. What I showed here in a compact way is just the concept of how it's possible to override the default behaviour. In a real world scenario I don't prefer to create special Editors just for a property, I'd create a Type and write an Editor for the whole type (in OPs case this would be some kind of collection type with special "selection" handling and maybe object creation and adding scenarios + convient presentation to the user. If you create the Edidor for a whole type you are much more flexible (think about VS design-time support etc.).
To your Points:

1. As I mentioned in the code commment - in real the Dialog would be just a normally designed dialog, and wouldn't have to "know" it is shown through the Editor. I just defined it in place to keep the code short - I think OP knows how to design a dialog. In the Type Editor you would just show it then. But I would instantiate it (and maybe hold the reference) inside the TypeEditor - so TestObject type would just have the Editor Attribute (on the type, not the property) and nothing more.
1a. - exactly (but if you use UITypeEditorEditStyle.Modal it has to be a Form)
2. Shure you can do that - whatever your scenario needs - but I wouldn't do it, because I think the object doesn't have to be aware of it's design - and maybe adding a dependency to PropertyGrid is not "nice" for a given type.
3. Yes of course - just did it inline to keep the code short
4. Thats the nice thing on the Component-Model in .NET - I didn't had a requirement in the past I didn't manage to fullfill. You can do that - and I think it's a good idea.

You are right about the "big effort" for such a thing - you have to write a lot of code! But most "shortcuts" I made in the past, needed "refactoring" to the "long" way later :-(

So now I feel lucky about your comment and thoughts to this Topic,

Kind regards Johannes
M_Mogharrabi 5-Oct-13 2:12am    
Eyval..., Thanks johannesnestler, that was exactly what i wanted. But there is a problem with your code.the selected value in the formDialog returns to the EditValue method but it does not set as TestProperty value! Is that my mistake?
johannesnestler 5-Oct-13 6:42am    
hmm - I testet it again. The code seems to be correct, i return the changed value from EditValue: value = listbox.SelectedItem; ... return value..
So I think you missed to return the correct selection value. What is missing from my example is the "other way round" as Bill pointed out in his 4th Point, would be a nice Feature - but I left that up to you, cause I wasn't expecting you would really use a "string" as property type. If you can't spot the error now, please post your code - maybe I can find it..
M_Mogharrabi 5-Oct-13 8:51am    
Excuse me johannes. I have found the problem,it was my mistake.I had set the ReadOnly attribute of TestProperty to true! I have removed it and now every thing works fine.
Thanks a lot and excuse me again.
Using Collection Class:

Private xItems() As New List (Of [MyClass])
Public Property Items() As List (Of [MyClass])
Get:
Return xItems

Set: (Value As List (Of [MyClass]))
xItems = Value

End Property
 
Share this answer
 

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