locked
How to implement WinForm UITypeEditor for collection property in AST.NET server control RRS feed

  • Question

  • User-718569536 posted

    Hi, It's my first time question in this forum. Please forgive me to put very long sentence in a single topic.

    There're several sample proggram in MS Help to implement UITypeEditor.
    Some are describing how to implement WindowsForm UITypeEditor for simple data type property (like string, integer, etc) of WindowsForm custom controls.
    Some are describing how to implement custom collection editor for collection type property for Web Serrver Controls.
    But there's no sample showing how to implement WinForm UITypeEditor for collection property of AST.NET server control.


    --------------------------------
    1. Passage to here
    --------------------------------
    I tried to make test program extending samples on MS help which shows way to achieve custom collection editor for ASP.Net server control.
    Main parts are as follows.


     --------------------------------
     *** custom server control main parts
     --------------------------------
        [
        AspNetHostingPermission(SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Minimal),
        AspNetHostingPermission(SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal),
        DefaultProperty("Contacts"),
        ParseChildren(true, "Contacts"),
        ToolboxData("<{0}:QuickContactsEx runat=\"server\"> </{0}:QuickContactsEx>")
        ]
        public class QuickContactsEx : WebControl
        {
            private StateManagedContactList contacts;

            [
            Category("Behavior"),
            Description("The contacts collection"),
            DesignerSerializationVisibility(
                DesignerSerializationVisibility.Content),
            // Editor(typeof(ContactCollectionEditor), typeof(UITypeEditor)), // <-[1] ***
            Editor(typeof(CustomContactsEditor), typeof(UITypeEditor)),   // <-[2] ***
            PersistenceMode(PersistenceMode.InnerDefaultProperty)
            ]
            public StateManagedContactList Contacts
            {
                get
                {
                    if (contacts == null)
                    {
                        contacts = new StateManagedContactList();
                        if (IsTrackingViewState)
                        {
                            ((IStateManager)contacts).TrackViewState();
                        }
                    }
                    return contacts;
                }
            }
            ........

    <-[1] is original code using ContactCollectionEditor which extends CollectionEditor.(it works and commented out)
    <-[2] is my code which is not works well.implementation for CustomConttacsEditor is as follows.

       --------------------------------
     *** implementation of CustomContactsEditor(which is used in [2])
     --------------------------------
     internal class CustomContactsEditor : UITypeEditor
        {
            public override UITypeEditorEditStyle GetEditStyle(
                System.ComponentModel.ITypeDescriptorContext context)
            {
                // <-[3] define editor style as ModalDailog ***
                return UITypeEditorEditStyle.Modal;
            }

            public override object EditValue( ITypeDescriptorContext context,
                IServiceProvider provider,  object value)
            {
                IWindowsFormsEditorService editorService = null;
                if (provider != null)
                {
                    editorService = provider.GetService(
                        typeof(IWindowsFormsEditorService))
                        as IWindowsFormsEditorService;
                }

                if (editorService != null)
                {
                    StateManagedContactList setValue = new StateManagedContactList();

                    // <-[4] ContactsCollectionSetterForm is a WindowsForm which provides list of contacts as a property 'MainList'.
                    //   I abbreviates code for restoring collection propterty to DialogForm here ***
                    ContactsCollectionSetterForm myDialog = new ContactsCollectionSetterForm();

                    if (editorService.ShowDialog(myDialog) == DialogResult.OK)
                    {
                        // <-[5] Converting colletion property in dialogform into list of Contacts
                        foreach (MyContact myItem in myDialog.MainList)
                        {
                            Contact newItem = new Contact();
                            newItem.Name = myItem.Name;
                            newItem.Email = myItem.EMail;
                            newItem.Phone = myItem.Phone;
                            setValue.Add(newItem);
                            Console.WriteLine(newItem.ToString());
                        }
                    }
                    else
                    {
                        Console.WriteLine("nothing happen!");
                    }
                    value = setValue;
                }
                return value;
            }
        }


    --------------------------------
    2. Result of above code
    --------------------------------

    In design mode, after I put this control on test web form, I can open dialog form when I click reference button in PropertyGrid of 'Contacts' property.
    But I cannot change property value even though I click OK button on the form(which return DialogResult.OK)

    Please let me know how to reflect collection property value into real property value using UITypeEditor in a case above.

    I have proved that I cant use WindowsForm UITypeEditor in ASP.NET custom server control if corresponding property type is simple one (like string or integer). Thus there must be a way to realize this.

    Any information will be appreciated. If any request, I can provide whole source code(which is about 700 rows code)

    Thank you.

    Saturday, August 29, 2009 12:06 AM

Answers

  • User-2106054853 posted

    Hi,

    Please try this. In reality you can pass value as a parameter of the constructor method of the form, and add values to it:

     

      internal class CustomContactsEditor : UITypeEditor
        {
            public CustomContactsEditor()
            {
            }

            public override UITypeEditorEditStyle GetEditStyle(
                System.ComponentModel.ITypeDescriptorContext context)
            {
                return UITypeEditorEditStyle.Modal;
            }

            public override object EditValue(
                ITypeDescriptorContext context,
                IServiceProvider provider,
                object value)
            {
                context.OnComponentChanging();
                IWindowsFormsEditorService editorService = null;
                if (provider != null)
                {
                    editorService =
                        provider.GetService(
                        typeof(IWindowsFormsEditorService))
                        as IWindowsFormsEditorService;
                }

                if (editorService != null)
                {
                    List<Contact> setValue = new List<Contact>();
                    ContactsCollectionSetterForm myDialog =
                        new ContactsCollectionSetterForm();
                    if (editorService.ShowDialog(myDialog) == DialogResult.OK)
                    {
                        foreach (MyContact myItem in myDialog.MainList)
                        {
                            Contact newItem = new Contact();
                            newItem.Name = myItem.Name;
                            newItem.Email = myItem.EMail;
                            newItem.Phone = myItem.Phone;
                            setValue.Add(newItem);
                            Console.WriteLine(newItem.ToString());
                        }
                    }
                    else
                    {
                        Console.WriteLine("nothing happen!");
                    }

                    foreach (var c in setValue) {
                        ((List<Contact>)value).Add(c);
                    }
                    //value = setValue;
                }
                MessageBox.Show("hello");
                context.OnComponentChanged();
                return value;
            }


        }

     

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Thursday, September 3, 2009 3:48 AM

All replies

  • User2130758966 posted

    As far as I know you can use the TypeConverter to provide something along these lines:

    Has to be for a real server control though, you cant use them on asp.net usercontrols.

    Saturday, August 29, 2009 6:34 AM
  • User-718569536 posted

    Hello Mr.All-Star. Thank you for your reply.

    Do you mean, it's impossible to use WindowsForm base Dialog for UITypeEditor on ASP.net UserControls?

    What I suffer is there's so less information or answer to this question in MS Help, in books and also in internet. It's first time that some one shows definit answer to this.

    But I found it's stranege, because for simple type property (like string, integer, etc), I've already implemented them for several real Server Controls, and it looks they are working properly.

    Thanks

    Saturday, August 29, 2009 6:32 PM
  • Sunday, August 30, 2009 11:40 PM
  • User-718569536 posted

     Thank you Mr. Chen. I'll Check.

    Monday, August 31, 2009 6:46 PM
  • User-718569536 posted

    Thank you Chen. I've checked your sample and found that you helped me proving that we can use WindowsForms Control for Web Control's custom UIType Editor. (Is it correct?)

    Now the first problem is solved, but the essential problem remains.
    "How to implement custom collection editor using UIType Editor for custom server controls."

    I have uploaded my sample programs in a site below.
    http://www.ad.il24.net/~masa_cmt/Samples/UITypeEditorTest01.zip

    Custom control and UITypeEditor definition is in a same source file under App_Code directory (QuickContactsEx.cs, I make it as simple as possible).

    Row 145 attribute for property "Contacts" is the matter. Above this line(in row 141) I commented out another attribute definition using normal collection editor, which works well.

    When you open QuickContactsExTest.aspx in design mode, and set focus on "QuickContatsEx" control , and click reference button on property grid for "Contacts" property, you will find that custom-made windows form (ContactCollectionSetterForm) pops up, and causes no result even if you click OK button. (That's what I suffer from)

    I think the main solution might to arrange CustomContactsEditor class'es overriden method "EditValue", but I don't know how.

    Any way I will try to check in specialized book for this topic.(I have ordered "Developing Microsoft Asp.Net Server Controls and Components" yesterday in amazon. There's no stock in Tokyo famous book stores. )

     

    Tuesday, September 1, 2009 9:13 AM
  • User-2106054853 posted

    Hi,

    Please try this. In reality you can pass value as a parameter of the constructor method of the form, and add values to it:

     

      internal class CustomContactsEditor : UITypeEditor
        {
            public CustomContactsEditor()
            {
            }

            public override UITypeEditorEditStyle GetEditStyle(
                System.ComponentModel.ITypeDescriptorContext context)
            {
                return UITypeEditorEditStyle.Modal;
            }

            public override object EditValue(
                ITypeDescriptorContext context,
                IServiceProvider provider,
                object value)
            {
                context.OnComponentChanging();
                IWindowsFormsEditorService editorService = null;
                if (provider != null)
                {
                    editorService =
                        provider.GetService(
                        typeof(IWindowsFormsEditorService))
                        as IWindowsFormsEditorService;
                }

                if (editorService != null)
                {
                    List<Contact> setValue = new List<Contact>();
                    ContactsCollectionSetterForm myDialog =
                        new ContactsCollectionSetterForm();
                    if (editorService.ShowDialog(myDialog) == DialogResult.OK)
                    {
                        foreach (MyContact myItem in myDialog.MainList)
                        {
                            Contact newItem = new Contact();
                            newItem.Name = myItem.Name;
                            newItem.Email = myItem.EMail;
                            newItem.Phone = myItem.Phone;
                            setValue.Add(newItem);
                            Console.WriteLine(newItem.ToString());
                        }
                    }
                    else
                    {
                        Console.WriteLine("nothing happen!");
                    }

                    foreach (var c in setValue) {
                        ((List<Contact>)value).Add(c);
                    }
                    //value = setValue;
                }
                MessageBox.Show("hello");
                context.OnComponentChanged();
                return value;
            }


        }

     

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Thursday, September 3, 2009 3:48 AM
  • User-718569536 posted

    Thank you Chen. I made it!!. It's a really evangelistic information to me.

    The critical point is following 2 things.
    --------------------------------
    1st)
    In "EditValue" method, call context.OnComponentChanging() at beginning, and call context.OnComponentChanged() at end right before set return value.

    2nd)
    Insert collection items into argument "value" and make it return value in "EditValue" method.
    (but it's no essential. I can replace "value" by "setValue" or just set "setValue" as return value)

    --------------------------------
    In accordance with your advice, I adjusted some part of the sample code. I made another Dialog Form's constructor which receives collection class as an argument, so I can pass "value" when I construct it in "EditValue".

    The corrected sample program is in the same site, same file name. I have just exchanged it.

    http://www.ad.il24.net/~masa_cmt/uitypeeditortest01.zip

    --------------------------------

    Any way, as far as I know, this is the first public sample of the "Custom Collection UI Type Editor using WindowsForm for ASP.NET Custom Control" in internet world. There's no similar information elsewhere, so it's a namely the world premiere.

    For those who suffer from same problem must see this. This will help them for developing any kind of custom dialog form property editor for ASP.Net custom controls.


    Thank you so much Chen. May force be with you!!

    (but I still have a very light weight problem relating this. I'll see you in another thread coming soon.)

    Friday, September 4, 2009 9:04 AM