Persisting control properties at design time

Discussion in 'ASP .Net Building Controls' started by cpnet, Apr 19, 2004.

  1. cpnet

    cpnet Guest

    Sorry, this is a 2nd post related to this problem, but I've now set up my
    MSDN e-mail id, so I wanted to post with this e-mail.

    I'm trying to build some custom controls/components for use with ASP.NET.
    I have ControlParent (I've tried this where ControlParent is a Control, and
    also where it's a WebControl descendent) and ComponentChild (a Component
    descendent). ControlParent has a ControlParent.ComponentChild property.
    In the designer, I drop both a ControlParent and ComponentChild on a
    WebForm. ComponentChild1 is listed in the dropdown for
    ControlParent1.ComponentChild in the designer. I can set
    ControlParent1.ComponentChild to ComponentChild1, and everything seems good.
    When I look at the HTML from my WebForm, I see ComponentChild1 listed as an
    attribute for my ControlParent1 control.

    However, if I rebuild my project, or close and reopen my WebForm, the
    ControlParent1.ComponentChild property is blank in the property pane of the
    designer. ComponentChild1 is still available in the dropdown, but it's no
    longer assigned (in the property pane). In the HTML, ComponentChild1 IS
    still assigned to ControlParen1.CompnentChild.

    I've tried messing around with TypeConverters and ControlDesigners, but
    haven't had any luck yet. I'm not sure what to do.

    I've also tried to get help at www.asp.net here
    http://www.asp.net/Forums/ShowPost.aspx?tabindex=1&PostID=539207, but so far
    I can't figure this out.

    Thanks,
    Chris
     
    cpnet, Apr 19, 2004
    #1
    1. Advertising

  2. Hi cpnet,

    Based on my understanding, you want to enable your ComponentChild to be
    selectable in the Property Browser for ControlParent, and also persist well.

    How do you implement to enable the ComponentChild to be selectable in the
    Property Browser for ControlParent?

    Normally, this is done through implement a TypeConverter for
    ControlParent.ComponentChild property , which provide the dropdownlist
    values through overriding GetStandardValues method.

    If you did just as I thought, the persistence is completed through
    overriding ConvertFrom and CanConvertFrom method. Once you do these
    correctly, the property should persist correct for you.

    For more information, please refer to "Type Converters That Provide a List
    of Standard Values to a Property Grid" section in the article below:
    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/htm
    l/cpconimplementingtypeconverter.asp

    If you did all these things, but the problem still existed, can you
    provided me some code snippet to reproduce this issue?

    Please clarify all these for me.

    Thank you for your patience and cooperation. If you have any questions or
    concerns, please feel free to post it in the group. I am standing by to be
    of assistance.

    Best regards,
    Jeffrey Tan
    Microsoft Online Partner Support
    Get Secure! - www.microsoft.com/security
    This posting is provided "as is" with no warranties and confers no rights.
     
    Jeffrey Tan[MSFT], Apr 20, 2004
    #2
    1. Advertising

  3. cpnet

    cpnet Guest

    Hi Jeffrey,

    When I don't implement any TypeConverter, I do see a list of the MyComponent
    components that I have on MyWebForm (in the dropdown for
    MyControl.MyComponent). However, the selected MyComponent doesn't persist
    when I close/re-open or rebuild my WebForm.

    When I create a direct descendent of TypeConverter for MyComponent (i.e.
    "MyComponentConverter: TypeConverter), and apply it to MyComponent with the
    TypeConverterAttribute, I seem to be able to replicate the behaviour I see
    with no TypeConverter. (I use some help from IReferenceServer to get the
    list of MyComponents on my WebForm for the StandardValuesCollection).
    However, I end up with the exact same persistence issue.

    I also noticed there was a ComponentConverter. When I try to create a
    descendent "MyComponentConverter: ComponentConverter", I can't get the
    GetStandardValues method to work.

    I guess for starters, I need to know if I should be creating a TypeConverter
    or ComponentConverter descendent. (I do realize that ComponentConverter is
    a descendent of TypeConverter, but I figured since MyComponent is a
    Component, maybe my converter needs to be a ComponentConverter)?

    Once I know which TypeConverter class I should descend from, I need to know
    which methods I need to override?

    I have seen the link you gave (and many like it). What all these
    TypeConverters do return a string representation of the class, or a new
    instance of the class corresponding to a string. What I need is to return a
    string representation of the name of an instance of my class, or given the
    name of an instance of my class located on a webform, return that actual
    instance of my class from the webform.

    Thanks,
    Chris


    ""Jeffrey Tan[MSFT]"" <> wrote in message
    news:XKaD%...
    > Hi cpnet,
    >
    > Based on my understanding, you want to enable your ComponentChild to be
    > selectable in the Property Browser for ControlParent, and also persist

    well.
    >
    > How do you implement to enable the ComponentChild to be selectable in the
    > Property Browser for ControlParent?
    >
    > Normally, this is done through implement a TypeConverter for
    > ControlParent.ComponentChild property , which provide the dropdownlist
    > values through overriding GetStandardValues method.
    >
    > If you did just as I thought, the persistence is completed through
    > overriding ConvertFrom and CanConvertFrom method. Once you do these
    > correctly, the property should persist correct for you.
    >
    > For more information, please refer to "Type Converters That Provide a List
    > of Standard Values to a Property Grid" section in the article below:
    >

    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/htm
    > l/cpconimplementingtypeconverter.asp
    >
    > If you did all these things, but the problem still existed, can you
    > provided me some code snippet to reproduce this issue?
    >
    > Please clarify all these for me.
    >
    > Thank you for your patience and cooperation. If you have any questions or
    > concerns, please feel free to post it in the group. I am standing by to be
    > of assistance.
    >
    > Best regards,
    > Jeffrey Tan
    > Microsoft Online Partner Support
    > Get Secure! - www.microsoft.com/security
    > This posting is provided "as is" with no warranties and confers no rights.
    >
     
    cpnet, Apr 21, 2004
    #3
  4. Hi cpnet,

    Thanks very much for your feedback.

    First, how is your "MyControl.MyComponent" implemented? If you did not
    specify TypeConverter on it, how can it have a list of values for selection
    in the DropDownList in Property Browser? Can you show me your implement
    details?

    So far as I think, you should do like this:

    Implement a TypeConverter for "MyControl.MyComponent", override its
    GetStandardValues method, to returns a collection of standard values for
    the data type this type converter is designed for.(This collection will
    appear in the dropdownlist in property browser)

    In the GetStandardValues method, in order to get all the components on the
    webform, you should use IReferenceService interface.

    Override TypeConverter's ConvertFrom and CanConvertFrom method, determine
    if the source type is string and source string is your expected one, you
    can get corresponding component's reference and return.(Also using
    IReferenceService interface)

    I think through these ways, it should work for you.

    Anyway, I will wait for your feedback.

    Thank you for your patience and cooperation. If you have any questions or
    concerns, please feel free to post it in the group. I am standing by to be
    of assistance.

    Best regards,
    Jeffrey Tan
    Microsoft Online Partner Support
    Get Secure! - www.microsoft.com/security
    This posting is provided "as is" with no warranties and confers no rights.
     
    Jeffrey Tan[MSFT], Apr 21, 2004
    #4
  5. cpnet

    cpnet Guest

    Hi Jeffrey,

    I'll have another stab at implementing a TypeConverter (descending directly
    from TypeConverter instead of ComponentConverter). In the meantime, here's
    my basic code (with no TypeConverter explictly assigned) that populates the
    dropdown list in the designer, but doesn't persist my property:
    http://www.sevolution.com/notc/

    Thanks,
    cpnet


    ""Jeffrey Tan[MSFT]"" <> wrote in message
    news:...
    > Hi cpnet,
    >
    > Thanks very much for your feedback.
    >
    > First, how is your "MyControl.MyComponent" implemented? If you did not
    > specify TypeConverter on it, how can it have a list of values for

    selection
    > in the DropDownList in Property Browser? Can you show me your implement
    > details?
    >
    > So far as I think, you should do like this:
    >
    > Implement a TypeConverter for "MyControl.MyComponent", override its
    > GetStandardValues method, to returns a collection of standard values for
    > the data type this type converter is designed for.(This collection will
    > appear in the dropdownlist in property browser)
    >
    > In the GetStandardValues method, in order to get all the components on the
    > webform, you should use IReferenceService interface.
    >
    > Override TypeConverter's ConvertFrom and CanConvertFrom method, determine
    > if the source type is string and source string is your expected one, you
    > can get corresponding component's reference and return.(Also using
    > IReferenceService interface)
    >
    > I think through these ways, it should work for you.
    >
    > Anyway, I will wait for your feedback.
    >
    > Thank you for your patience and cooperation. If you have any questions or
    > concerns, please feel free to post it in the group. I am standing by to be
    > of assistance.
    >
    > Best regards,
    > Jeffrey Tan
    > Microsoft Online Partner Support
    > Get Secure! - www.microsoft.com/security
    > This posting is provided "as is" with no warranties and confers no rights.
    >
     
    cpnet, Apr 21, 2004
    #5
  6. cpnet

    cpnet Guest

    Hi again,

    I've tried implementing the TypeConverter, but I'm still having problems. I
    did get further by inheriting from TypeConverter directly (rather than
    ComponentConverter). However, I'm having problems getting the Components'
    names. Right now what I see in the dropdown, and in my HTML, is the
    Component name followed by it's Type in square brackets - i.e.:
    "MyComponent1 [MyComponent]" instead of simply "MyComponent1". This extra
    type info is messing things up, and I can't get rid of it.

    My code is here: http://www.sevolution.com/tc

    Thanks,
    cpnet
     
    cpnet, Apr 21, 2004
    #6
  7. Hi cpnet,

    Thanks very much for your feedback.

    Oh, after viewing your code, I have reproduced out your issue.
    Actually, Component class has ComponentConverter attribute, so at
    design-time, it will get all the components in the designer and list them
    in the dropdownlist in Property Browser. For more information, please refer
    to ComponentConverter in MSDN

    So we should not implement TypeConverter for this property.

    I will spend some time on this issue. I will reply to you ASAP.

    Thanks for your understanding.

    Thank you for your patience and cooperation. If you have any questions or
    concerns, please feel free to post it in the group. I am standing by to be
    of assistance.

    Best regards,
    Jeffrey Tan
    Microsoft Online Partner Support
    Get Secure! - www.microsoft.com/security
    This posting is provided "as is" with no warranties and confers no rights.
     
    Jeffrey Tan[MSFT], Apr 22, 2004
    #7
  8. Hi cpnet,

    Sorry for letting you wait for so long time.

    After some research, I think you may workaround this issue through change
    your property's type to string instead of Component. This will enable the
    designer successfully deserialize the html view's string properly. At
    design-time, when you want to use this property to get the string related
    component reference, you may use IReferenceService interface to get the
    component's reference through IReferenceService.GetReference method.

    At this way, you should implement a StringConverter for your property and
    get all the components on the designer.

    Like this:

    public class MyComponentConverter: StringConverter
    {
    public override StandardValuesCollection
    GetStandardValues(ITypeDescriptorContext context)
    {
    if (context == null || context.Container == null)
    {
    return null;
    }
    IReferenceService
    irs=(IReferenceService)context.GetService(typeof(IReferenceService));

    ArrayList arr = new ArrayList();

    foreach (IComponent comp in context.Container.Components)
    {
    if(comp is System.ComponentModel.Component)
    {
    string name=irs.GetName(comp);
    arr.Add(string.Copy(name));
    }
    }

    object [] ctls = arr.ToArray();
    if (ctls != null)
    {
    return new StandardValuesCollection(ctls);
    }
    else
    {
    return null;
    }
    }

    public override bool GetStandardValuesExclusive(ITypeDescriptorContext
    context)
    {
    return false;
    }

    public override bool GetStandardValuesSupported(ITypeDescriptorContext
    context)
    {
    return true;
    }
    }

    [TypeConverter(typeof(MyComponentConverter))]
    public string testComponent
    {
    get
    {
    object o = ViewState["testComponent"];
    return((o == null) ? String.Empty : (string)o);
    }
    set
    {
    ViewState["testComponent"] = value;
    }
    }

    ===================================
    Please apply my suggestion above and let me know if it helps resolve your
    problem.

    Thank you for your patience and cooperation. If you have any questions or
    concerns, please feel free to post it in the group. I am standing by to be
    of assistance.

    Best regards,
    Jeffrey Tan
    Microsoft Online Partner Support
    Get Secure! - www.microsoft.com/security
    This posting is provided "as is" with no warranties and confers no rights.
     
    Jeffrey Tan[MSFT], Apr 23, 2004
    #8
  9. cpnet

    cpnet Guest

    Hi Jeffrey,

    I don't think that's going to quite do what I want. I want my property to
    be of type MyComponent, not String. Users of my component will be using
    this property at design time AND runtime. I'm going to look pretty bad if I
    tell them they have to use one property at design time, and a different one
    at runtime.

    I'm sure what I want can be done, I just don't know how. If you look at a
    DataGrid, it has a DataSource property of type Object. The drop down
    'detects' any Object on the WebForm that implements IEnumerable (for example
    any DataSet component). It displays the string name in the designer, but
    the property is an Object. You can use the same property at design or
    runtime, and the settings persist when rebuilding or closing/reopening your
    WebForm. This is the behaviour I need.

    When I look at the DataGrid/DataSet example, I see the following in my HTML:

    <asp:DataGrid id="DataGrid1" ... DataSource=" <#% DataSet1
    %>"></asp:DataGrid>

    Where as my code is:

    <cc1:MyControl id="MyControl1" ...
    MyComponent="MyComponent1"></cc1:MyControl>

    The datagrid has added in that extra stuff around the property value's
    name - ie <#% %>. I guess I probably need to get my Control to add that
    stuff into my HTML. I'm assuming that will tell ASP.NET to evaluate the
    string name of the MyComponent attribute to the name of an instance of a
    control. Any ideas on what class I should look at to do this?

    Thanks
    cpnet


    ""Jeffrey Tan[MSFT]"" <> wrote in message
    news:...
    > Hi cpnet,
    >
    > Sorry for letting you wait for so long time.
    >
    > After some research, I think you may workaround this issue through change
    > your property's type to string instead of Component. This will enable the
    > designer successfully deserialize the html view's string properly. At
    > design-time, when you want to use this property to get the string related
    > component reference, you may use IReferenceService interface to get the
    > component's reference through IReferenceService.GetReference method.
    >
    > At this way, you should implement a StringConverter for your property and
    > get all the components on the designer.
    >
    > Like this:
    >
    > public class MyComponentConverter: StringConverter
    > {
    > public override StandardValuesCollection
    > GetStandardValues(ITypeDescriptorContext context)
    > {
    > if (context == null || context.Container == null)
    > {
    > return null;
    > }
    > IReferenceService
    > irs=(IReferenceService)context.GetService(typeof(IReferenceService));
    >
    > ArrayList arr = new ArrayList();
    >
    > foreach (IComponent comp in context.Container.Components)
    > {
    > if(comp is System.ComponentModel.Component)
    > {
    > string name=irs.GetName(comp);
    > arr.Add(string.Copy(name));
    > }
    > }
    >
    > object [] ctls = arr.ToArray();
    > if (ctls != null)
    > {
    > return new StandardValuesCollection(ctls);
    > }
    > else
    > {
    > return null;
    > }
    > }
    >
    > public override bool GetStandardValuesExclusive(ITypeDescriptorContext
    > context)
    > {
    > return false;
    > }
    >
    > public override bool GetStandardValuesSupported(ITypeDescriptorContext
    > context)
    > {
    > return true;
    > }
    > }
    >
    > [TypeConverter(typeof(MyComponentConverter))]
    > public string testComponent
    > {
    > get
    > {
    > object o = ViewState["testComponent"];
    > return((o == null) ? String.Empty : (string)o);
    > }
    > set
    > {
    > ViewState["testComponent"] = value;
    > }
    > }
    >
    > ===================================
    > Please apply my suggestion above and let me know if it helps resolve your
    > problem.
    >
    > Thank you for your patience and cooperation. If you have any questions or
    > concerns, please feel free to post it in the group. I am standing by to be
    > of assistance.
    >
    > Best regards,
    > Jeffrey Tan
    > Microsoft Online Partner Support
    > Get Secure! - www.microsoft.com/security
    > This posting is provided "as is" with no warranties and confers no rights.
    >
     
    cpnet, Apr 23, 2004
    #9
  10. Hi cpnet,

    Thanks for your feedback.

    I have seen your concern. I am currently doing research on this issue,
    which need some time. I will reply to you ASAP

    Thanks for your understanding.

    Best regards,
    Jeffrey Tan
    Microsoft Online Partner Support
    Get Secure! - www.microsoft.com/security
    This posting is provided "as is" with no warranties and confers no rights.
     
    Jeffrey Tan[MSFT], Apr 28, 2004
    #10
  11. Hello Cpnet,

    I have contacted our ASP.NET product group on this issue to see what their
    opinion is. I will reply here with more information as soon as possible.
    Thanks very much.

    Best regards,
    Yanhong Huang
    Microsoft Community Support

    Get Secure! ┬ĘC www.microsoft.com/security
    This posting is provided "AS IS" with no warranties, and confers no rights.
     
    Yan-Hong Huang[MSFT], Apr 29, 2004
    #11
  12. Hi cpnet,

    Sorry for letting you wait for so long time.

    After contacting Asp.net product group, I got some useful feedback and
    solution.

    Yes, we should follow DataSource property's implement of persist object
    property.

    Normally, for object type property, at design-time we should provide a
    ControlDesigner for the control, which provide a string representation
    property for this object type property to persist. We normally use
    ControlDesigner.DataBindings(which override
    HtmlControlDesigner.DataBindings) property to store the string
    representation.

    The solution like this:

    namespace TestProject
    {

    [DefaultProperty("Text"),
    ToolboxData("<{0}:SimpleControl runat=server></{0}:SimpleControl>")]
    [Designer(typeof(SimpleControlDesigner))]
    public class SimpleControl :
    System.Web.UI.WebControls.WebControl,INamingContainer
    {
    private string text;
    [Bindable(true),
    Category("Appearance"),
    DefaultValue("")]
    public string Text
    {
    get
    {
    return text;
    }
    set
    {
    text = value;
    }
    }

    private Component myComponent=null;

    [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
    public Component testComponent
    {
    get
    {
    return myComponent;
    }
    set
    {
    myComponent = value;
    }
    }

    protected override void Render(HtmlTextWriter output)
    {
    output.Write(Text);
    }
    }

    public class SimpleControlDesigner : ControlDesigner
    {

    public string testComponent
    {
    get
    {
    DataBinding binding = DataBindings["testComponent"];

    if (binding != null)
    {
    return binding.Expression;
    }
    return String.Empty;
    }
    set
    {
    if ((value == null) || (value.Length == 0))
    {
    DataBindings.Remove("testComponent");
    }
    else
    {
    DataBinding binding = DataBindings["testComponent"];

    if (binding == null)
    {
    binding = new DataBinding("testComponent", typeof(Component), value);
    }
    else
    {
    binding.Expression = value;
    }
    DataBindings.Add(binding);
    }
    OnBindingsCollectionChanged("testComponent");

    IContainer container = (IContainer)this.GetService(typeof(IContainer));
    ((SimpleControl)Component).testComponent =
    (Component)container.Components[value];
    }
    }

    protected override void PreFilterProperties(IDictionary properties)
    {
    base.PreFilterProperties(properties);

    PropertyDescriptor prop;

    prop = (PropertyDescriptor)properties["testComponent"];

    System.ComponentModel.AttributeCollection runtimeAttributes =
    prop.Attributes;
    Attribute[] attrs = new Attribute[runtimeAttributes.Count + 1];

    runtimeAttributes.CopyTo(attrs, 0);
    attrs[runtimeAttributes.Count] = new
    TypeConverterAttribute(typeof(MyComponentConverter));
    prop = TypeDescriptor.CreateProperty(this.GetType(), "testComponent",
    typeof(string),attrs);
    properties["testComponent"] = prop;
    }
    }

    public class MyComponentConverter : TypeConverter
    {

    public override StandardValuesCollection
    GetStandardValues(ITypeDescriptorContext context)
    {

    object[] components = null;

    if (context != null)
    {
    ArrayList list = new ArrayList();
    list.Add(null);

    IContainer cont = context.Container;
    if (cont != null)
    {
    ComponentCollection objs = cont.Components;

    foreach(IComponent obj in objs)
    {
    if (obj is Component)
    {
    list.Add(obj.Site.Name);
    }
    }
    }

    components = list.ToArray();
    }

    return new StandardValuesCollection(components);
    }

    public override bool GetStandardValuesExclusive(ITypeDescriptorContext
    context)
    {
    return true;
    }

    public override bool GetStandardValuesSupported(ITypeDescriptorContext
    context)
    {
    return true;
    }
    }
    }

    This works well on my machine.

    =======================================
    Please apply my suggestion above and let me know if it helps resolve your
    problem.

    Thank you for your patience and cooperation. If you have any questions or
    concerns, please feel free to post it in the group. I am standing by to be
    of assistance.

    Best regards,
    Jeffrey Tan
    Microsoft Online Partner Support
    Get Secure! - www.microsoft.com/security
    This posting is provided "as is" with no warranties and confers no rights.
     
    Jeffrey Tan[MSFT], Apr 30, 2004
    #12
  13. cpnet

    cpnet Guest

    Thanks Jeffrey,

    I won't get a chance to look at this until next week, but I'll let you know
    as soon as I try it out - it looks promising.

    cpnet

    ""Jeffrey Tan[MSFT]"" <> wrote in message
    news:...
    > Hi cpnet,
    >
    > Sorry for letting you wait for so long time.
    >
    > After contacting Asp.net product group, I got some useful feedback and
    > solution.
    >
    > Yes, we should follow DataSource property's implement of persist object
    > property.
    >
    > Normally, for object type property, at design-time we should provide a
    > ControlDesigner for the control, which provide a string representation
    > property for this object type property to persist. We normally use
    > ControlDesigner.DataBindings(which override
    > HtmlControlDesigner.DataBindings) property to store the string
    > representation.
    >
    > The solution like this:
    >
    > namespace TestProject
    > {
    >
    > [DefaultProperty("Text"),
    > ToolboxData("<{0}:SimpleControl runat=server></{0}:SimpleControl>")]
    > [Designer(typeof(SimpleControlDesigner))]
    > public class SimpleControl :
    > System.Web.UI.WebControls.WebControl,INamingContainer
    > {
    > private string text;
    > [Bindable(true),
    > Category("Appearance"),
    > DefaultValue("")]
    > public string Text
    > {
    > get
    > {
    > return text;
    > }
    > set
    > {
    > text = value;
    > }
    > }
    >
    > private Component myComponent=null;
    >
    > [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
    > public Component testComponent
    > {
    > get
    > {
    > return myComponent;
    > }
    > set
    > {
    > myComponent = value;
    > }
    > }
    >
    > protected override void Render(HtmlTextWriter output)
    > {
    > output.Write(Text);
    > }
    > }
    >
    > public class SimpleControlDesigner : ControlDesigner
    > {
    >
    > public string testComponent
    > {
    > get
    > {
    > DataBinding binding = DataBindings["testComponent"];
    >
    > if (binding != null)
    > {
    > return binding.Expression;
    > }
    > return String.Empty;
    > }
    > set
    > {
    > if ((value == null) || (value.Length == 0))
    > {
    > DataBindings.Remove("testComponent");
    > }
    > else
    > {
    > DataBinding binding = DataBindings["testComponent"];
    >
    > if (binding == null)
    > {
    > binding = new DataBinding("testComponent", typeof(Component), value);
    > }
    > else
    > {
    > binding.Expression = value;
    > }
    > DataBindings.Add(binding);
    > }
    > OnBindingsCollectionChanged("testComponent");
    >
    > IContainer container = (IContainer)this.GetService(typeof(IContainer));
    > ((SimpleControl)Component).testComponent =
    > (Component)container.Components[value];
    > }
    > }
    >
    > protected override void PreFilterProperties(IDictionary properties)
    > {
    > base.PreFilterProperties(properties);
    >
    > PropertyDescriptor prop;
    >
    > prop = (PropertyDescriptor)properties["testComponent"];
    >
    > System.ComponentModel.AttributeCollection runtimeAttributes =
    > prop.Attributes;
    > Attribute[] attrs = new Attribute[runtimeAttributes.Count + 1];
    >
    > runtimeAttributes.CopyTo(attrs, 0);
    > attrs[runtimeAttributes.Count] = new
    > TypeConverterAttribute(typeof(MyComponentConverter));
    > prop = TypeDescriptor.CreateProperty(this.GetType(), "testComponent",
    > typeof(string),attrs);
    > properties["testComponent"] = prop;
    > }
    > }
    >
    > public class MyComponentConverter : TypeConverter
    > {
    >
    > public override StandardValuesCollection
    > GetStandardValues(ITypeDescriptorContext context)
    > {
    >
    > object[] components = null;
    >
    > if (context != null)
    > {
    > ArrayList list = new ArrayList();
    > list.Add(null);
    >
    > IContainer cont = context.Container;
    > if (cont != null)
    > {
    > ComponentCollection objs = cont.Components;
    >
    > foreach(IComponent obj in objs)
    > {
    > if (obj is Component)
    > {
    > list.Add(obj.Site.Name);
    > }
    > }
    > }
    >
    > components = list.ToArray();
    > }
    >
    > return new StandardValuesCollection(components);
    > }
    >
    > public override bool GetStandardValuesExclusive(ITypeDescriptorContext
    > context)
    > {
    > return true;
    > }
    >
    > public override bool GetStandardValuesSupported(ITypeDescriptorContext
    > context)
    > {
    > return true;
    > }
    > }
    > }
    >
    > This works well on my machine.
    >
    > =======================================
    > Please apply my suggestion above and let me know if it helps resolve your
    > problem.
    >
    > Thank you for your patience and cooperation. If you have any questions or
    > concerns, please feel free to post it in the group. I am standing by to be
    > of assistance.
    >
    > Best regards,
    > Jeffrey Tan
    > Microsoft Online Partner Support
    > Get Secure! - www.microsoft.com/security
    > This posting is provided "as is" with no warranties and confers no rights.
    >
     
    cpnet, May 1, 2004
    #13
  14. Hi cpnet,

    Ok, I will wait for your feedback. Thanks

    Best regards,
    Jeffrey Tan
    Microsoft Online Partner Support
    Get Secure! - www.microsoft.com/security
    This posting is provided "as is" with no warranties and confers no rights.
     
    Jeffrey Tan[MSFT], May 3, 2004
    #14
  15. cpnet

    cpnet Guest

    That code seemed to do the trick... thanks for your help!


    ""Jeffrey Tan[MSFT]"" <> wrote in message
    news:...
    > Hi cpnet,
    >
    > Sorry for letting you wait for so long time.
    >
    > After contacting Asp.net product group, I got some useful feedback and
    > solution.
    >
    > Yes, we should follow DataSource property's implement of persist object
    > property.
    >
    > Normally, for object type property, at design-time we should provide a
    > ControlDesigner for the control, which provide a string representation
    > property for this object type property to persist. We normally use
    > ControlDesigner.DataBindings(which override
    > HtmlControlDesigner.DataBindings) property to store the string
    > representation.
    >
    > The solution like this:
    >
    > namespace TestProject
    > {
    >
    > [DefaultProperty("Text"),
    > ToolboxData("<{0}:SimpleControl runat=server></{0}:SimpleControl>")]
    > [Designer(typeof(SimpleControlDesigner))]
    > public class SimpleControl :
    > System.Web.UI.WebControls.WebControl,INamingContainer
    > {
    > private string text;
    > [Bindable(true),
    > Category("Appearance"),
    > DefaultValue("")]
    > public string Text
    > {
    > get
    > {
    > return text;
    > }
    > set
    > {
    > text = value;
    > }
    > }
    >
    > private Component myComponent=null;
    >
    > [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
    > public Component testComponent
    > {
    > get
    > {
    > return myComponent;
    > }
    > set
    > {
    > myComponent = value;
    > }
    > }
    >
    > protected override void Render(HtmlTextWriter output)
    > {
    > output.Write(Text);
    > }
    > }
    >
    > public class SimpleControlDesigner : ControlDesigner
    > {
    >
    > public string testComponent
    > {
    > get
    > {
    > DataBinding binding = DataBindings["testComponent"];
    >
    > if (binding != null)
    > {
    > return binding.Expression;
    > }
    > return String.Empty;
    > }
    > set
    > {
    > if ((value == null) || (value.Length == 0))
    > {
    > DataBindings.Remove("testComponent");
    > }
    > else
    > {
    > DataBinding binding = DataBindings["testComponent"];
    >
    > if (binding == null)
    > {
    > binding = new DataBinding("testComponent", typeof(Component), value);
    > }
    > else
    > {
    > binding.Expression = value;
    > }
    > DataBindings.Add(binding);
    > }
    > OnBindingsCollectionChanged("testComponent");
    >
    > IContainer container = (IContainer)this.GetService(typeof(IContainer));
    > ((SimpleControl)Component).testComponent =
    > (Component)container.Components[value];
    > }
    > }
    >
    > protected override void PreFilterProperties(IDictionary properties)
    > {
    > base.PreFilterProperties(properties);
    >
    > PropertyDescriptor prop;
    >
    > prop = (PropertyDescriptor)properties["testComponent"];
    >
    > System.ComponentModel.AttributeCollection runtimeAttributes =
    > prop.Attributes;
    > Attribute[] attrs = new Attribute[runtimeAttributes.Count + 1];
    >
    > runtimeAttributes.CopyTo(attrs, 0);
    > attrs[runtimeAttributes.Count] = new
    > TypeConverterAttribute(typeof(MyComponentConverter));
    > prop = TypeDescriptor.CreateProperty(this.GetType(), "testComponent",
    > typeof(string),attrs);
    > properties["testComponent"] = prop;
    > }
    > }
    >
    > public class MyComponentConverter : TypeConverter
    > {
    >
    > public override StandardValuesCollection
    > GetStandardValues(ITypeDescriptorContext context)
    > {
    >
    > object[] components = null;
    >
    > if (context != null)
    > {
    > ArrayList list = new ArrayList();
    > list.Add(null);
    >
    > IContainer cont = context.Container;
    > if (cont != null)
    > {
    > ComponentCollection objs = cont.Components;
    >
    > foreach(IComponent obj in objs)
    > {
    > if (obj is Component)
    > {
    > list.Add(obj.Site.Name);
    > }
    > }
    > }
    >
    > components = list.ToArray();
    > }
    >
    > return new StandardValuesCollection(components);
    > }
    >
    > public override bool GetStandardValuesExclusive(ITypeDescriptorContext
    > context)
    > {
    > return true;
    > }
    >
    > public override bool GetStandardValuesSupported(ITypeDescriptorContext
    > context)
    > {
    > return true;
    > }
    > }
    > }
    >
    > This works well on my machine.
    >
    > =======================================
    > Please apply my suggestion above and let me know if it helps resolve your
    > problem.
    >
    > Thank you for your patience and cooperation. If you have any questions or
    > concerns, please feel free to post it in the group. I am standing by to be
    > of assistance.
    >
    > Best regards,
    > Jeffrey Tan
    > Microsoft Online Partner Support
    > Get Secure! - www.microsoft.com/security
    > This posting is provided "as is" with no warranties and confers no rights.
    >
     
    cpnet, May 7, 2004
    #15
  16. Hi cpnet,

    Thanks for your feedback.

    I am glad to hear that :). If you need further help, please feel free to
    post. Thanks

    Best regards,
    Jeffrey Tan
    Microsoft Online Partner Support
    Get Secure! - www.microsoft.com/security
    This posting is provided "as is" with no warranties and confers no rights.
     
    Jeffrey Tan[MSFT], May 10, 2004
    #16
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Allan Ebdrup
    Replies:
    11
    Views:
    660
    Walter Wang [MSFT]
    Jul 26, 2007
  2. J.Marsch

    Persisting Design-time generated value

    J.Marsch, Oct 7, 2003, in forum: ASP .Net Building Controls
    Replies:
    2
    Views:
    130
    Mike Clay
    Oct 13, 2003
  3. Alessandro Zifiglio

    Persisting properties in templates and not the control itself

    Alessandro Zifiglio, Nov 9, 2003, in forum: ASP .Net Building Controls
    Replies:
    0
    Views:
    172
    Alessandro Zifiglio
    Nov 9, 2003
  4. Peter

    properties not showing in properties window at design time

    Peter, Dec 10, 2003, in forum: ASP .Net Building Controls
    Replies:
    1
    Views:
    213
    Lostinet.Web Support
    Dec 10, 2003
  5. Steve Barker

    Properties not persisting at design time.

    Steve Barker, Jan 22, 2004, in forum: ASP .Net Building Controls
    Replies:
    0
    Views:
    154
    Steve Barker
    Jan 22, 2004
Loading...

Share This Page