Help! custom TypeConverter/Persistence problems...

S

Sky Sigal

My goal is to keep public properties of a custom Control neatly tied
together -- rather than all over the IDE.

One such set of values that will rarely be changed, so should have little
priority in the IDE Properties panel, is maybe Captions that are used
through the text.

So assuming that I made the following class

class MyControl : WebControl {
....

public class cCaptions {
public string _Btn_Submit = "Login";
public string _Btn_NewUser = "Register";
public string Btn_Submit {get{return _Btn_Submit;}set{_Btn_Submit=value;}}
public string Btn_NewUser {get{return
_Btn_NewUser;}set{_Btn_NewUser=value;}}
}//Subclass:End
....

private cCaptions _Captions = new cCaptions;
....
[TypeConverter(typeof(TestConverter)),
PersistenceMode(PersistenceMode.Attribute )]
public cCaptions {get {return _Captions;}set {_Captions = value;}
....
}//Control:End


As you can see the public property now requires a custom TypeConverter so
that it can be seen in the IDE -- and deal with persistence as an attribute.

I originally thought/tried using the standard ExpandableObject one -- but I
needed a way to persist it in one string -- just like how style="" attribute
is done, with : and ; as sep chars between key and value...


Well.
The TypeConverter I wrote works atleast for converting between object and
string, and now in the IDE's Property panel I get the expandableObject look
(+/- tree) as well as a means of reading it as one string which looks like

<MyControl CAPTIONS="Btn_Submit:Login;Btn_NewUser:Register"></MyControl>


My problem with this is that it all LOOKS right -- but its not acting
right...


Problems/Observations:
a) When I edit the string directly in the Properties panel -- eg change it
to "Btn_Submit:HELLO;Btn_NewUser:Come on in!" it ---well...doesn't do it.
The moment I hit Save -- it reverts back to to the default values. :-(
b) When I click + to expand the Expandable options, and edit the Btn_Submit
value directly -- it updates the summary string line/title to the new
values -- AND updates the interface's actual label (I have to hit save to
get this to trigger)-- but when I check the Html of the control -- its not
been notified of the changes and still shows default values...
c) If I edit the Html of the Control to another value. Nothing happens.


In other words -- total disconnection between the values of the property --
and what is persisted.

Anybody have an idea?


I attach the TypeConverter that I wrote in case it is the cause -- or if
not, that it may be the starting point for someone else...





using System;
using System.Web.UI.Design;
using System.Web;
using System.ComponentModel;
using System.Globalization;
using System.Reflection;
using System.Collections;

namespace XAct.Web.Controls {

public class TestConverter : ExpandableObjectConverter {
System.Type _Type = typeof(XAct.Web.Controls.LoginPanel.cCaptions);

public override bool CanConvertFrom(ITypeDescriptorContext context, Type t)
{
if (t == typeof(string)) {return true;}
return base.CanConvertFrom(context, t);
}

public override object ConvertFrom(ITypeDescriptorContext context,
CultureInfo info,object value) {
if (value is string) {
string[] tParts;
tParts = SplitPlus((string) value, ";");
object o = _Type.Assembly.CreateInstance(_Type.ToString());
string tKey = string.Empty;
string tValue = string.Empty;
int tPos = 0;
foreach (string tPart in tParts){
if (tPart == string.Empty){continue;}
tPos = tPart.IndexOf(':');
if (tPos == -1){
tPos = tPart.Length;
tKey = tPart;
tValue = string.Empty;
}else{
tKey = tPart.Substring(0,tPos);
tValue = tPart.Substring(tPos+1);
System.Reflection.PropertyInfo oPI =
_Type.GetProperty(tKey,System.Reflection.BindingFlags.SetProperty |
System.Reflection.BindingFlags.Public
|System.Reflection.BindingFlags.IgnoreCase);
if (oPI != null){
oPI.SetValue(o,tValue,null);
}
}
}
return o;
}
return base.ConvertFrom(context, info, value);
}
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo
culture, object value, Type destType) {
object o=null;
try {
o = System.Convert.ChangeType(value,_Type);
}catch{}
if ((o !=null) && (destType == typeof(string))) {
string tResult = string.Empty;
string tDivChar = string.Empty;
PropertyInfo[] oPIs = _Type.GetProperties();
foreach(PropertyInfo oPI in oPIs){
string tKey = oPI.Name;
object oVal = oPI.GetValue(o,null);
string tValue = string.Empty;
if (oVal != null){
tValue = oVal.ToString();
if (tValue != string.Empty){tResult += tDivChar + tKey + ":" + tValue;}
if (tDivChar == string.Empty){tDivChar = ";";}
}
}
return tResult;
}
return base.ConvertTo(context, culture, value, destType);
}

/// <summary>
/// Split function that only splits if not within brackets or quotes.
/// </summary>
/// <param name="qString"></param>
/// <param name="qDivChar"></param>
/// <returns></returns>
public static string[] SplitPlus(string qString, string qDivChar) {
if (qDivChar== String.Empty){qDivChar = ",";}
ArrayList tResults = new ArrayList();
string tChar="";
string tWord = "";
bool tEscaped=false;
string tLastChar = "";
System.Collections.Stack tQuotes=new System.Collections.Stack();
for (int i=0;i<qString.Length;i++) {
tChar = qString.ToString();
if (tQuotes.Count == 0) {
//We are outside of quotes, so look for quote beginnings...
if ((tChar == "(") ||
(tChar == "{") ||
(tChar == "[") ||
(tChar == "'") ||
(tChar == "\"")) {
tQuotes.Push(tChar);
tLastChar=tChar;
}
if ((tChar == qDivChar)) {
tResults.Add(tWord);
tWord="";
tChar = "";
}
}
else {
//We are within quotes...need to look for close chars:
if (tEscaped ==false) {
if (tChar == "\\") {tEscaped=true;}
else {
tLastChar =(string)tQuotes.Peek();
if ((tChar == "\"") && (tChar == tLastChar)) {
tQuotes.Pop();
}
else if ((tChar == "\'") && (tChar == tLastChar)) {
tQuotes.Pop();
}
else if ((tChar == "]") && (tLastChar == "[")) {
tQuotes.Pop();
}
else if ((tChar == "}") && (tLastChar == "{")) {
tQuotes.Pop();
}
if ((tChar == ")") && (tLastChar == "(")) {
tQuotes.Pop();
}
}
}
else {
tEscaped = false;
}
}
tWord = tWord+tChar;
}
if (tWord!= String.Empty) {tResults.Add(tWord);}
return (string[])tResults.ToArray(typeof(string));
}
}//Class:End
}
 

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,483
Members
44,901
Latest member
Noble71S45

Latest Threads

Top