Persisting control properties at design time

C

cpnet

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
 
J

Jeffrey Tan[MSFT]

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.
 
C

cpnet

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]" said:
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.
 
J

Jeffrey Tan[MSFT]

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.
 
C

cpnet

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
 
C

cpnet

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
 
J

Jeffrey Tan[MSFT]

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.
 
J

Jeffrey Tan[MSFT]

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.
 
C

cpnet

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]" said:
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.
 
J

Jeffrey Tan[MSFT]

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.
 
Y

Yan-Hong Huang[MSFT]

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.
 
J

Jeffrey Tan[MSFT]

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.
 
C

cpnet

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]" said:
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.
 
J

Jeffrey Tan[MSFT]

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.
 
C

cpnet

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


"Jeffrey Tan[MSFT]" said:
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.
 
J

Jeffrey Tan[MSFT]

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.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top