How to create an object property for a custom UserControl?

Hi all..

I created a UserControl where I implemented a property that if of a class type.

I want that in VS.NET editor this property to be shown as a tree, something similar to Font property present in most visual controls.

Do I have to include some attribute or to make something special with the property

Thanks

Jaime




Answer this question

How to create an object property for a custom UserControl?

  • JohanNL

    Hello..

    Finally I've found the solution by seeing examples in http://www.codeproject.com/cs/miscctrl/customizingcollectiondata.asp and in http://www.codeproject.com/cs/miscctrl/MonthCalendar.asp.

    Thanks anyway

    Jaime



  • Kalaka

    Thanks for your answer.. I used a type converter but I'm receiving the following strange error:

    Unable to cast object of type 'VidaSecurity.Windows.Forms.RUTBox' to type 'VidaSecurity.Windows.Forms.RUTBox'.

    Where VidaSecurity.Windows.Forms.RUTBox is the UserControl. I realized that when I enter some value in properties list of the property of an object type, ConvertFrom method is called.

    Well.. landing a little more the problem...

    UserControl is named RUTBox. It has a property of type RUTType, where RUTType has 2 public propeties: "Principal" and "Digito".

    When I add the control to the Form, I can see the RUTType property in the properties list of he designer, which actually shows both properties as a tree. I created StringConverters for both properties so that they validates that the input texts are correct.

    Both converters work but I have the following behaviours:

    - When I modify the value of a property of RUTType, main RUTType property isn't updated with a formated string joining boh properties

    - When I enter a text directly into the RUType property, the error: "Unable to cast object of type 'VidaSecurity.Windows.Forms.RUTBox' to type 'VidaSecurity.Windows.Forms.RUTBox'." occurs, even when I commented ConvertFrom method out of the TypeConverter (what is actually a ExpandableObjectConverter)

    Any help would be greatly appreciated.

    Thanks

    Jaime

    These are all type converters:

    internal class RUTTypeConverter : ExpandableObjectConverter

    {

    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)

    {

    if (sourceType == typeof(string))

    return true;

    return base.CanConvertFrom(context, sourceType);

    }

    public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)

    {

    if (destinationType == typeof(string))

    return true;

    return base.CanConvertTo(context, destinationType);

    }

    /* public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)

    {

    if (value is string)

    {

    string[] ss = value.ToString().Split(new char[] {'-'}, 2);

    if (ss.Length == 2)

    {

    RUTType item;

    RUTBox r = (RUTBox)context.Instance;

    item = r.RUT;

    if (item.Parent.ValidaRut(ss[0].Trim(), ss[1].Trim()))

    {

    item.Principal = ss[0].Trim();

    item.Digito = ss[1].Trim();

    return item;

    }

    }

    throw new ArgumentException("RUT invalido.");

    }

    return base.ConvertFrom(context, culture, value);

    }*/

    /* public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)

    {

    if (destinationType == typeof(string))

    {

    //string rutStr = String.Empty;

    //RUTType dest = (RUTType)value;

    return "hola";

    if (dest.Parent.IsValid)

    {

    rutStr = dest.Numero;

    if (dest.Parent.UseFormat)

    {

    rutStr.Replace('.', '\0');

    rutStr = String.Format("{0:###,###,###}-{1}", int.Parse(rutStr), dest.DigitoVerificador);

    }

    else

    rutStr = String.Format("{0}-{1}", rutStr, dest.DigitoVerificador);

    }

    return rutStr;

    }

    return base.ConvertTo(context, culture, value, destinationType);

    }*/

    }

    internal class DigitoConverter : StringConverter

    {

    public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)

    {

    if (destinationType == typeof(string))

    {

    string[] validDigits = new string[] {"0", "1", "2", "3", "4", "5", "6",

    "7", "8", "9", "K"};

    if (value.GetType() == typeof(string))

    {

    for (int i = 0; i < validDigits.Length; i++)

    {

    if (value.ToString().ToUpper().CompareTo(validDigitsIdea) == 0)

    return validDigitsIdea;

    }

    }

    else if (value.GetType() == typeof(int))

    {

    int d = Convert.ToInt32(value);

    if ((d >= 0) && (d <= 9))

    return value;

    }

    throw new ArgumentException("Digito verificador invalido");

    }

    return base.ConvertTo(context, culture, value, destinationType);

    }

    public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)

    {

    if (value.GetType() == typeof(string))

    {

    string ret = Convert.ToString(value).ToUpper();

    string[] validDigits = new string[] {"0", "1", "2", "3", "4", "5", "6",

    "7", "8", "9", "K"};

    if (ret.Length == 1 )

    for (int i = 0; i < validDigits.Length; i++)

    {

    if (ret.CompareTo(validDigitsIdea) == 0)

    return validDigitsIdea;

    }

    else

    if (ret.Length > 1)

    throw new ArgumentException("Digito verificador invalido.");

    }

    return base.ConvertFrom(context, culture, value);

    }

    }

    internal class PrincipalConverter : StringConverter

    {

    public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)

    {

    if (destinationType == typeof(string))

    {

    int ret;

    if (int.TryParse(Convert.ToString(value), out ret))

    return Convert.ToString(value);

    else

    throw new ArgumentException("Parte principal del RUT invalida");

    }

    else throw new ArgumentException("Invalid");

    }

    public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)

    {

    if (value.GetType() == typeof(string))

    {

    int len = Convert.ToString(value).Length;

    int ret;

    if (len <= 8 && int.TryParse(Convert.ToString(value), out ret))

    return value;

    else

    if (len > 0 )

    throw new ArgumentException("La parte principal solo puede ser numerica y con a lo mas 8 digitos.");

    }

    return base.ConvertFrom(context, culture, value);

    }

    }



  • Nezo

    Hello,

    A. Create a custom TypeConverter for your class

    <System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.Demand, Name:="FullTrust")> _
    Public Class NodeViewTypeConverter
    Inherits TypeConverter

    Public Sub New()
    MyBase.New()
    End Sub 'New

    Public Overloads Overrides Function GetPropertiesSupported(ByVal context As ITypeDescriptorContext) As Boolean
    Return True
    End Function 'GetPropertiesSupported

    Public Overloads Overrides Function GetProperties(ByVal context As ITypeDescriptorContext, _
    ByVal value As Object, _
    ByVal attributes As Attribute()) As PropertyDescriptorCollection
    ' PropertyType returns the Type of the class which was adorned with this TypeConverter.
    Return TypeDescriptor.GetProperties(context.PropertyDescriptor.PropertyType)
    End Function 'GetProperties

    End Class 'NodeViewTypeConverter

    B. Apply TypeConverter to your class using the TypeConverterAttribute - You may need to supply a fully or partially qualified path so it can find it (eg YourProject.YourClass.ect)

    <TypeConverter(GetType(NodeViewTypeConverter))> _
    Public Class YourObjectClass

    C, Apply the SerializationDesignerVisibility attribute to the property that is of type YourObjectClass

    Private m_TestProperty As YourObjectClass = New YourObjectClass
    <DesignerSerializationVisibility(DesignerSerializationVisibility.Content)> _
    Public Property TestProperty() As YourObjectClass
    Get
    Return m_TestProperty
    End Get
    Set(ByVal value As TestProperty)
    m_TestProperty = value
    End Set
    End Property 'TestProperty

    D. Override ToString in YourObjectClass

    Public Overloads Overrides Function ToString() As String
    Return String.Empty
    End Function 'ToString

    This should present your class in the designer with a + sign next to it. When you click it you should then see the individual properties. If you forget the DesignerSerializationVisibility attribute your properties will not be serialized to the form. Good Luck!


  • How to create an object property for a custom UserControl?