记得去年年初的时候做了一个Colorful ListBox Control控件。当时考虑的因数很少,虽然那个控件实现了简单的调用接口,可是有一个致命的问题是居然没有考虑到PostBack后的状态保存问题

    新的ColorableListBox解决了控件被PostBack后的状态保存。实现过程很简单,就是把ListItem的ForeColor和BackColor信息存在ViewState里面,自己在控件中去维护。这个功能本来是很简单的,可是在做完后发现也仍然并不完美,因为目前还是不能处理条目移动的问题,如果条目被移动,比如有删除和插入等操作等,ListItem的颜色不能同步。目前的处理办法是如果有ListItem的变动,就清空所有的色彩信息。

    执行流程,在控件的OnPerRender事件运触发时,判断ListBox的Item的Attributes.CssStyle属性里是否被设置了color和background-color属性。如果有就记录下其属性值,然后保存在ViewState里,PostBack后从ViewState里恢复Item的属性值,在Render事件里,使用自己保存的属性信息来修改<option ...>...</option>的css属性。 

protected override void OnPreRender(EventArgs e)
{
    
if ( m_IsClear )
    
{
        m_ItemStyles 
= null;
    }


    ArrayList alstStyle 
= null;
    Hashtable htItemStyles 
= null;

    
forint i=0 ; i < this.Items.Count ; ++i )
    
{
        
if ( alstStyle != null )
        
{
            alstStyle.Clear();
        }

        
foreachstring key in this.Items[i].Attributes.CssStyle.Keys )
        
{
            
if ( htItemStyles == null )
            
{
                htItemStyles 
= new Hashtable();
            }

            
if ( m_ItemStyles != null )
            
{
                
foreachobject obj in m_ItemStyles )
                
{
                    
object [] objs = (object [])obj;
                    htItemStyles[objs[
0]] = objs[1];
                }

            }

            
if ( alstStyle == null )
            
{
                alstStyle 
= new ArrayList();
            }

            
string strKey = key.ToLower();
            
if ( strKey == "color" || strKey == "background-color" )
            
{
                alstStyle.Add(key 
+ ':' + this.Items[i].Attributes.CssStyle[key]);
                
continue;
            }

        }

        
if ( alstStyle != null && alstStyle.Count > 0 )
        
{
            
string [] strAry = new string[alstStyle.Count];
            alstStyle.CopyTo(strAry);
            htItemStyles[i] 
= strAry;
        }
            
    }

    
if ( htItemStyles != null )
    
{
        
int count = 0;
        m_ItemStyles 
= new object[htItemStyles.Count];
        
foreachobject key in htItemStyles.Keys )
        
{
            
object [] objects = new object[2];
            objects[
0= key;
            objects[
1= (string [])htItemStyles[key];
            m_ItemStyles[count
++= objects;
        }

    }

    
base.OnPreRender(e);
}

    控件的使用方法为:
 ColorableListBox clb = new ColorableListBox();
 ListItem li 
= new ListItem(name, value);
 li.Attributes.CssStyle.Add(
"color""yellow");
 li.Attributes.CssStyle.Add(
"background-color""blue");
 clb.Items.Add(li);
    如果重新设置条目后(比如有Insert和Delete操作等)需要调用一下:ClearItemStyles();
#region 附ColorableListBox控件源码
using System;
using System.IO;
using System.Collections;
using System.Text;
using System.Text.RegularExpressions;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;

namespace WebExcel.UI.WebControls
{
    
/// <summary>
    
/// Summary description for ColorableListBox.
    
/// </summary>

    [DefaultProperty("Text")]
    [ToolboxData(
"<{0}:ColorableListBox runat=server></{0}:ColorableListBox>")]
    
public class ColorableListBox : ListBox
    
{
        
private object [] m_ItemStyles;
        
private bool m_IsClear = false;

        
protected override object SaveViewState()
        
{
            ArrayList alstViewState 
= new ArrayList();
            
object objBaseVS = base.SaveViewState();
            alstViewState.Add(objBaseVS);
            alstViewState.Add(m_ItemStyles);
            
return alstViewState;
        }


        
protected override void LoadViewState(object savedState)
        
{
            
if ( savedState != null )
            
{
                ArrayList alstViewState 
= (ArrayList)savedState;
                
if ( alstViewState.Count >= 1 )
                
{
                    
base.LoadViewState(alstViewState[0]);
                }

                
if ( alstViewState.Count == 2 )
                
{
                    m_ItemStyles 
= (object [])alstViewState[1];
                }

            }

        }

        
        
protected override void OnPreRender(EventArgs e)
        
{
            
if ( m_IsClear )
            
{
                m_ItemStyles 
= null;
            }


            ArrayList alstStyle 
= null;
            Hashtable htItemStyles 
= null;

            
forint i=0 ; i < this.Items.Count ; ++i )
            
{
                
if ( alstStyle != null )
                
{
                    alstStyle.Clear();
                }

                
foreachstring key in this.Items[i].Attributes.CssStyle.Keys )
                
{
                    
if ( htItemStyles == null )
                    
{
                        htItemStyles 
= new Hashtable();
                    }

                    
if ( m_ItemStyles != null )
                    
{
                        
foreachobject obj in m_ItemStyles )
                        
{
                            
object [] objs = (object [])obj;
                            htItemStyles[objs[
0]] = objs[1];
                        }

                    }

                    
if ( alstStyle == null )
                    
{
                        alstStyle 
= new ArrayList();
                    }

                    
string strKey = key.ToLower();
                    
if ( strKey == "color" || strKey == "background-color" )
                    
{
                        alstStyle.Add(key 
+ ':' + this.Items[i].Attributes.CssStyle[key]);
                        
continue;
                    }

                }

                
if ( alstStyle != null && alstStyle.Count > 0 )
                
{
                    
string [] strAry = new string[alstStyle.Count];
                    alstStyle.CopyTo(strAry);
                    htItemStyles[i] 
= strAry;
                }
            
            }

            
if ( htItemStyles != null )
            
{
                
int count = 0;
                m_ItemStyles 
= new object[htItemStyles.Count];
                
foreachobject key in htItemStyles.Keys )
                
{
                    
object [] objects = new object[2];
                    objects[
0= key;
                    objects[
1= (string [])htItemStyles[key];
                    m_ItemStyles[count
++= objects;
                }

            }

            
base.OnPreRender(e);
        }


        
/// <summary>
        
/// clear custom item styles
        
/// </summary>

        public void ClearItemStyles()
        
{
            m_IsClear 
= true;
        }


        
public override void DataBind()
        
{
            ClearItemStyles();
            
base.DataBind ();
        }


        
/// <summary> 
        
/// Render this control to the output parameter specified.
        
/// </summary>
        
/// <param name="output"> The HTML writer to write out to </param>

        protected override void Render(HtmlTextWriter output)
        
{
            StringBuilder strb 
= new StringBuilder();
            StringWriter sw 
= new StringWriter(strb);
            HtmlTextWriter htw 
= new HtmlTextWriter(sw);
            
base.Render(htw);
            
            
if ( m_ItemStyles != null )
            
{
                
foreachobject obj in m_ItemStyles )
                
{
                    
object [] objs = (object [])obj;
                    
int i = (int)objs[0];
                    AppendColorAttributes(strb, 
this.Items[i], (string [])objs[1]);
                }

            }

            output.Write(strb.ToString());
        }


        
private void AppendColorAttributes(StringBuilder select, ListItem li, string [] styles)
        
{
            
string strItemPattern = @"value=""{0}""{1}>{2}</option>";
            
string strOriginalItem = string.Format(strItemPattern, li.Value, "", li.Text);
            
string strStyle = " style=\"";
            forint i=0 ; i < styles.Length ; i++ )
            
{
                
string [] keyvalue = styles[i].Split(new char [] {':'});
                
string strStyleKey = keyvalue[0];
                
string strStyleValue = keyvalue[1];
                strStyle 
+= String.Format("{0}:{1};", strStyleKey.ToLower(), strStyleValue);
            }

            strStyle 
+= @"""";
            
string strNewItem = string.Format(strItemPattern, li.Value, strStyle, li.Text);
            select.Replace(strOriginalItem, strNewItem);
        }

    }

}

#endregion