T
Tom
I am developing a page that will contain multiple instances of a
Composite Custom Control that i have developed. The problem is that
the user will determine at run time how many of the control will be
added to the page at runtime (through add or delete button clicks). I
have created a class for the control(PersonPanel), and have created a
collection class(PersonPanelCollection)to hold and store all the
controls at runtime, but due to the page lifecycle in ASP.net, the
control collection(PersonPanelCollection) goes out of scope after the
page is destroyed. I read that i need to persist this object to the
page's viewstate(so as to hold all the information in the control
collection) and on each page request recast this control back to the
collection class(PersonPanelCollection). When i attempted this it
gave me an error saying i need to make the collection
class(PersonPanelCollection) serializable or create a type converter
for the class. From my understanding, a type converter is the way to
go over serialization for performance reasons - more data written to
the viewstate. I have since written a TypeConverter for each the
Control class(PersonPanel) and it collection
class(PersonPanelCollection), but i cannot cast the control to a
string to be written to the viewstate(VS.net complains that the class
does not support conversion to this type), nor if i use the
..ToString() method of the classes does it return any data. What do i
need to do to get this to work? Does the type conversion happen
automatically by just doing a cast, or is there something more to
this? My code is below:
[ToolboxData("<{0}ersonPanel runat=server></{0}ersonPanel>"),
TypeConverter(typeof(PersonPanelConverter))]
public class PersonPanel : System.Web.UI.WebControls.Panel,
INamingContainer
{
.... Person Panel class constructor, methods, etc.
}
public class PersonPanelConverter : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context,
Type sourceType)
{
if (sourceType == typeof(string))
{
return true;
}
return base.CanConvertFrom(context, sourceType);
}
public override object ConvertFrom(ITypeDescriptorContext context,
CultureInfo culture, object value)
{
if (value is string)
{
...Logic to do the conversion and return the new PersonPanel object
}
return base.ConvertFrom(context, culture, value);
}
public override object ConvertTo(ITypeDescriptorContext Context,
CultureInfo culture, object value, Type destinationType)
{
if (destinationType == typeof(string))
{
...Logic to do the conversion and return the string
}
return base.ConvertTo(context, culture, value, destinationType);
}
}
[ TypeConverter(typeof(PersonPanelCollectionConverter))]
public class PersonPanelCollection :
System.Collections.CollectionBase, INamingContainer
{
public PersonPanelCollection()
{
}
public PersonPanel this[ int index ]
{
get
{
return( (PersonPanel) List[index] );
}
set
{
List[index] = value;
}
}
public int Add( PersonPanel value )
{
return(List.Add( value ) );
}
public int IndexOf(int value )
{
return( List.IndexOf( value ) );
}
public void Insert( int index, PersonPanel value )
{
List.Insert( index, value );
}
public void Remove(PersonPanel value )
{
List.Remove( value );
}
}
public class PersonPanelCollectionConverter : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context,
Type sourceType)
{
if (sourceType == typeof(string))
{
return true;
}
return base.CanConvertFrom(context, sourceType);
}
public override object ConvertFrom(ITypeDescriptorContext context,
CultureInfo culture, object value)
{
if (value is string)
{
..Logic to to create a new PersonPanelCollection, and use the
PersonPanel's TypeConverter to create a new panel for each of the
panel's in the collection - cannot cast as VS complains that it does
not support the case for each panel so i use the ToString() method
}
return base.ConvertFrom(context, culture, value);
}
public override object ConvertTo(ITypeDescriptorContext context,
CultureInfo culture, object value, Type destinationType)
{
StringBuilder tempSB = new StringBuilder();
if (destinationType == typeof(string))
{
...create the string representation of the object and return it
}
return base.ConvertTo(context, culture, value, destinationType);
}
}
Composite Custom Control that i have developed. The problem is that
the user will determine at run time how many of the control will be
added to the page at runtime (through add or delete button clicks). I
have created a class for the control(PersonPanel), and have created a
collection class(PersonPanelCollection)to hold and store all the
controls at runtime, but due to the page lifecycle in ASP.net, the
control collection(PersonPanelCollection) goes out of scope after the
page is destroyed. I read that i need to persist this object to the
page's viewstate(so as to hold all the information in the control
collection) and on each page request recast this control back to the
collection class(PersonPanelCollection). When i attempted this it
gave me an error saying i need to make the collection
class(PersonPanelCollection) serializable or create a type converter
for the class. From my understanding, a type converter is the way to
go over serialization for performance reasons - more data written to
the viewstate. I have since written a TypeConverter for each the
Control class(PersonPanel) and it collection
class(PersonPanelCollection), but i cannot cast the control to a
string to be written to the viewstate(VS.net complains that the class
does not support conversion to this type), nor if i use the
..ToString() method of the classes does it return any data. What do i
need to do to get this to work? Does the type conversion happen
automatically by just doing a cast, or is there something more to
this? My code is below:
[ToolboxData("<{0}ersonPanel runat=server></{0}ersonPanel>"),
TypeConverter(typeof(PersonPanelConverter))]
public class PersonPanel : System.Web.UI.WebControls.Panel,
INamingContainer
{
.... Person Panel class constructor, methods, etc.
}
public class PersonPanelConverter : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context,
Type sourceType)
{
if (sourceType == typeof(string))
{
return true;
}
return base.CanConvertFrom(context, sourceType);
}
public override object ConvertFrom(ITypeDescriptorContext context,
CultureInfo culture, object value)
{
if (value is string)
{
...Logic to do the conversion and return the new PersonPanel object
}
return base.ConvertFrom(context, culture, value);
}
public override object ConvertTo(ITypeDescriptorContext Context,
CultureInfo culture, object value, Type destinationType)
{
if (destinationType == typeof(string))
{
...Logic to do the conversion and return the string
}
return base.ConvertTo(context, culture, value, destinationType);
}
}
[ TypeConverter(typeof(PersonPanelCollectionConverter))]
public class PersonPanelCollection :
System.Collections.CollectionBase, INamingContainer
{
public PersonPanelCollection()
{
}
public PersonPanel this[ int index ]
{
get
{
return( (PersonPanel) List[index] );
}
set
{
List[index] = value;
}
}
public int Add( PersonPanel value )
{
return(List.Add( value ) );
}
public int IndexOf(int value )
{
return( List.IndexOf( value ) );
}
public void Insert( int index, PersonPanel value )
{
List.Insert( index, value );
}
public void Remove(PersonPanel value )
{
List.Remove( value );
}
}
public class PersonPanelCollectionConverter : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context,
Type sourceType)
{
if (sourceType == typeof(string))
{
return true;
}
return base.CanConvertFrom(context, sourceType);
}
public override object ConvertFrom(ITypeDescriptorContext context,
CultureInfo culture, object value)
{
if (value is string)
{
..Logic to to create a new PersonPanelCollection, and use the
PersonPanel's TypeConverter to create a new panel for each of the
panel's in the collection - cannot cast as VS complains that it does
not support the case for each panel so i use the ToString() method
}
return base.ConvertFrom(context, culture, value);
}
public override object ConvertTo(ITypeDescriptorContext context,
CultureInfo culture, object value, Type destinationType)
{
StringBuilder tempSB = new StringBuilder();
if (destinationType == typeof(string))
{
...create the string representation of the object and return it
}
return base.ConvertTo(context, culture, value, destinationType);
}
}