论Web控件开发 - 树状控件(一)

我曾经一直梦想拥有象windows窗体开发中一样易使用的WebMenu、WebTreeNavigatorPanel、WebDropDownTree等树结构的Web控件,当理解asp.net后我发现实现他们将不再是一个梦,目前我已经初步开发出了这些树状控件,在今后有时间的日子愿把开发心得与大家分享。

一、树状结构框架
首先针对视图状态我开发了两个基类ViewStatePartBase和ViewStatePartCollectionBase,今后所有Menu、TreeNavigator、DropDownTree的Item、ItemColleciton均从他们继承。为了便于理解这两个基类的作用,首先我们先来开发一个简单的控件WinPop来说明基类的用法。

WinPop组件主要用在网站的首页,当用户请求主页时,它会根据控件中的Items属性(弹出窗口链接地址,弹出窗口属性等等)来弹出多个窗口。其开发原型如下: 
winpop1.jpg

以下是ViewStatePartBase的源代码

None.gif using  System;
None.gif
using  System.Web.UI;
None.gif
using  System.Web.UI.WebControls;
None.gif
using  System.Web.UI.Design;
None.gif
using  System.Drawing.Design;
None.gif
using  System.Drawing;
None.gif
using  System.ComponentModel;
None.gif
using  System.ComponentModel.Design;
None.gif
using  System.Collections;
None.gif
None.gif
namespace  Keyss.WebControls
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
public abstract class ViewStatePartBase:IStateManager
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
ContractedSubBlock.gifExpandedSubBlockStart.gif        
viewstate#region viewstate
InBlock.gif        
protected bool _isTrackingViewState;
InBlock.gif        
protected StateBag _viewState;
InBlock.gif 
InBlock.gif        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
InBlock.gif        [EditorBrowsable(EditorBrowsableState.Never)]
InBlock.gif        [Browsable(
false)]
InBlock.gif        
public virtual bool IsTrackingViewState 
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif            
get dot.gifreturn _isTrackingViewState; } 
ExpandedSubBlockEnd.gif        }

InBlock.gif        [EditorBrowsable(EditorBrowsableState.Never)]
InBlock.gif        
public virtual void LoadViewState(object savedState) 
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
if(savedState != null)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                ((IStateManager)ViewState).LoadViewState(savedState);
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif        [EditorBrowsable(EditorBrowsableState.Never)]
InBlock.gif        
public virtual object SaveViewState() 
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
object savedState = null;
InBlock.gif            
if(!IsEmpty) 
InBlock.gif                savedState 
= ((IStateManager)_viewState).SaveViewState();
InBlock.gif            
return savedState;
ExpandedSubBlockEnd.gif        }

InBlock.gif        [EditorBrowsable(EditorBrowsableState.Never)]
InBlock.gif        
public virtual void TrackViewState() 
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            _isTrackingViewState 
= true;
InBlock.gif            
if(_viewState!=null)
InBlock.gif                ((IStateManager)_viewState).TrackViewState();
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif        
#endregion

ContractedSubBlock.gifExpandedSubBlockStart.gif        
helper#region helper
InBlock.gif        [
InBlock.gif        Browsable(
false),
InBlock.gif        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
InBlock.gif        ]
InBlock.gif        
protected virtual StateBag ViewState 
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
get 
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
if(_viewState == null
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    _viewState 
= new StateBag(false);
InBlock.gif                    
if(_isTrackingViewState) 
ExpandedSubBlockStart.gifContractedSubBlock.gif                    
dot.gif{
InBlock.gif                        ((IStateManager)_viewState).TrackViewState();
ExpandedSubBlockEnd.gif                    }

ExpandedSubBlockEnd.gif                }

InBlock.gif                
return _viewState;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
InBlock.gif        [Browsable(
false)]
InBlock.gif        
public virtual bool IsEmpty 
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif            
get dot.gifreturn (_viewState == null||ViewState.Count==0); } 
ExpandedSubBlockEnd.gif        }

InBlock.gif        [EditorBrowsable(EditorBrowsableState.Never)]
InBlock.gif        
public virtual void SetDirty()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
if(!IsEmpty)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                ICollection Keys 
= _viewState.Keys;
InBlock.gif                
foreach(string key in Keys)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    _viewState.SetItemDirty(key, 
true);
ExpandedSubBlockEnd.gif                }

ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif        [EditorBrowsable(EditorBrowsableState.Never)]
InBlock.gif        
public virtual bool IsSet(string key)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
if((!IsEmpty)&&(_viewState[key]!=null))
InBlock.gif                
return true;
InBlock.gif            
return false;
ExpandedSubBlockEnd.gif        }

InBlock.gif        [EditorBrowsable(EditorBrowsableState.Never)]
InBlock.gif        
public virtual void RemoveItem(string key)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
if((_viewState[key]!=null))
InBlock.gif                
this._viewState.Remove(key);
ExpandedSubBlockEnd.gif        }

InBlock.gif        [EditorBrowsable(EditorBrowsableState.Never)]
InBlock.gif        
public virtual void Reset()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            _viewState 
= null;
ExpandedSubBlockEnd.gif        }

InBlock.gif        [EditorBrowsable(EditorBrowsableState.Never)]
InBlock.gif        
protected virtual void CopyFrom(ViewStatePartBase s)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{    
InBlock.gif            
if((s!=null)&&(!s.IsEmpty))
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{    
InBlock.gif                
foreach(string key in s.ViewState.Keys)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    ViewState.Add(key,s.ViewState[key]);
ExpandedSubBlockEnd.gif                }

ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif        [EditorBrowsable(EditorBrowsableState.Never)]
InBlock.gif        
protected virtual void MergeWith(ViewStatePartBase s)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
if((s!=null)&&(!s.IsEmpty))
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
foreach(string key in s.ViewState.Keys)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    
if(!IsSet(key))
InBlock.gif                        ViewState.Add(key,s.ViewState[key]);
ExpandedSubBlockEnd.gif                }

ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif        
#endregion

ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

None.gif


从上面的源代码可以看到ViewStatePartBase实现了IStateManager接口,除了标准的四个接口函数以外还实现了几个工具函数用来帮助对视图状态中保存的条目进行操作。其中Reset、MergeWith和CopyFrom主要针对自定义的样式类(如MenuItemStyle等等)操作。

以下是ViewStatePartBaseCollection的源代码

None.gif using  System;
None.gif
using  System.Web.UI;
None.gif
using  System.Web.UI.WebControls;
None.gif
using  System.Web.UI.Design;
None.gif
using  System.Drawing.Design;
None.gif
using  System.Drawing;
None.gif
using  System.Collections;
None.gif
using  System.ComponentModel;
None.gif
using  System.ComponentModel.Design;
None.gif
None.gif
namespace  Keyss.WebControls
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    [ 
InBlock.gif    PersistenceMode(PersistenceMode.InnerProperty),
InBlock.gif    ] 
InBlock.gif    
public abstract class ViewStatePartCollectionBase:System.Collections.CollectionBase,IStateManager
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
ContractedSubBlock.gifExpandedSubBlockStart.gif        
viewstate#region viewstate
InBlock.gif        
protected bool _isTrackingViewState;
InBlock.gif
InBlock.gif        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
InBlock.gif        [EditorBrowsable(EditorBrowsableState.Never)]
InBlock.gif        [Browsable(
false)]
InBlock.gif        
public virtual bool IsTrackingViewState 
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif            
get dot.gifreturn _isTrackingViewState; } 
ExpandedSubBlockEnd.gif        }

InBlock.gif        [EditorBrowsable(EditorBrowsableState.Never)]
InBlock.gif        
public virtual void LoadViewState(object savedState) 
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
if(savedState != null)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{    
InBlock.gif                Pair savedPair 
= (Pair)savedState;
InBlock.gif                ArrayList collectionState 
= (ArrayList)savedPair.First;
InBlock.gif                ArrayList collectionIndex 
= (ArrayList)savedPair.Second;
InBlock.gif
InBlock.gif                
for(int i = 0;i < collectionState.Count; i++)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    
int index = (int)collectionIndex[i];
InBlock.gif                    
if(index < Count)
InBlock.gif                        ((ViewStatePartBase)InnerList[index]).LoadViewState(collectionState[i]);
InBlock.gif                    
else
ExpandedSubBlockStart.gifContractedSubBlock.gif                    
dot.gif{
InBlock.gif                        ViewStatePartBase item 
= this.NewItem();
InBlock.gif                        item.LoadViewState(collectionState[i]);    
InBlock.gif                        AddItem(item);
ExpandedSubBlockEnd.gif                    }

ExpandedSubBlockEnd.gif                }

ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif        
protected abstract ViewStatePartBase NewItem();
InBlock.gif        
protected virtual int AddItem(ViewStatePartBase item)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
if(item!=null)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
if(this._isTrackingViewState)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    item.TrackViewState();
InBlock.gif                    item.SetDirty();
ExpandedSubBlockEnd.gif                }

InBlock.gif                
this.InnerList.Add(item);
InBlock.gif                
return this.InnerList.Count - 1;
ExpandedSubBlockEnd.gif            }

InBlock.gif            
else
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
throw new ArgumentNullException("item","item can't be null!");
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif        [EditorBrowsable(EditorBrowsableState.Never)]
InBlock.gif        
public virtual object SaveViewState() 
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{    
InBlock.gif            
if(this.Count > 0)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                ArrayList collectionState;
InBlock.gif                ArrayList collectionIndex;
InBlock.gif
InBlock.gif                collectionState 
= new ArrayList();
InBlock.gif                collectionIndex 
= new ArrayList();
InBlock.gif                
for(int i=0;i< Count;i++)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    
object tmpState = ((ViewStatePartBase)InnerList[i]).SaveViewState();
InBlock.gif                    
if(tmpState!=null)
ExpandedSubBlockStart.gifContractedSubBlock.gif                    
dot.gif{
InBlock.gif                        collectionState.Add(tmpState);
InBlock.gif                        collectionIndex.Add(i);
ExpandedSubBlockEnd.gif                    }
                    
ExpandedSubBlockEnd.gif                }

InBlock.gif                
if(collectionState.Count > 0)
InBlock.gif                    
return new Pair(collectionState,collectionIndex);
ExpandedSubBlockEnd.gif            }

InBlock.gif            
return null;
ExpandedSubBlockEnd.gif        }

InBlock.gif        [EditorBrowsable(EditorBrowsableState.Never)]
InBlock.gif        
public virtual void TrackViewState() 
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            _isTrackingViewState 
= true;
InBlock.gif            
for(int i=0;i<Count;i++)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                ((ViewStatePartBase)InnerList[i]).TrackViewState();
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif        
#endregion

ContractedSubBlock.gifExpandedSubBlockStart.gif        
helper function#region helper function
InBlock.gif        
public virtual bool IsEmpty
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif            
get dot.gif{return Count==0;}
ExpandedSubBlockEnd.gif        }

InBlock.gif        
public virtual void SetDirty()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
for(int i = 0;i< Count ;i++)
InBlock.gif                ((ViewStatePartBase)InnerList[i]).SetDirty();
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif        
#endregion

ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

None.gif
None.gif


由代码可以看到,ViewStatePartCollectionBase从CollectionBase继承,这保证在设计器中会为此属性提供集合编辑器,而PersistenceMode(PersistenceMode.InnerProperty)属性则保证在页面序列化时会把其中的内容作为内部子属性来实现, 如下面Items属性所示:
Web.jpg

而除了实现自身直接属性的视图状态管理以外还实现了其中包含的Items的状态管理,另外为了今后可以从用程序载入Item并支持视图状态管理,还实现了AddItem方法。为了简单,目前集合中只支持添加操作,并不支持插入、删除等操作,因为如果支持这些操作则还要考虑保存所有的Items中的视图状态情况比较烦锁,而一般来讲通常这些组件都是在第一次请求时装载,在回传情况下通过视图状态恢复,所以一般情况下已经够用。

下面是WinPopItem的实现

None.gif using  System;
None.gif
using  System.Web.UI;
None.gif
using  System.Web.UI.WebControls;
None.gif
using  System.Web.UI.Design;
None.gif
using  System.Drawing.Design;
None.gif
using  System.Drawing;
None.gif
None.gif
using  System.ComponentModel;
None.gif
using  System.ComponentModel.Design;
None.gif
None.gif
namespace  Keyss.WebControls
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {    
InBlock.gif    [TypeConverter(
typeof(ExpandableObjectConverter))]
InBlock.gif    
public class WinPopItem:ViewStatePartBase
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
ContractedSubBlock.gifExpandedSubBlockStart.gif        
const#region const
InBlock.gif        
public const string TargetUrlKey = "B";
InBlock.gif        
public const string TargetFrameKey = "C";
InBlock.gif        
public const string TargetFeaturesKey = "D";
InBlock.gif        
public const string ReplaceKey = "E";
ExpandedSubBlockEnd.gif        
#endregion

ContractedSubBlock.gifExpandedSubBlockStart.gif        
field#region field
InBlock.gif        [
InBlock.gif        NotifyParentProperty(
true), 
InBlock.gif        Bindable(
true),
InBlock.gif        Category(
"Appearance"),
InBlock.gif        DefaultValue(
"")
InBlock.gif        ]
InBlock.gif        
public string TargetUrl 
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif
InBlock.gif            
get 
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif
InBlock.gif                
object o = ViewState[TargetUrlKey];
InBlock.gif                
return (o == null)?string.Empty:(string)o;
ExpandedSubBlockEnd.gif            }
 
InBlock.gif            
set 
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif
InBlock.gif                ViewState[TargetUrlKey] 
= value; 
ExpandedSubBlockEnd.gif            }
 
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        [
InBlock.gif        NotifyParentProperty(
true), 
InBlock.gif        Bindable(
true),
InBlock.gif        Category(
"Appearance"),
InBlock.gif        DefaultValue(
"")
InBlock.gif        ]
InBlock.gif        
public string TargetFrame 
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif
InBlock.gif            
get 
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif
InBlock.gif                
object o = ViewState[TargetFrameKey];
InBlock.gif                
return (o == null)?string.Empty:(string)o;
ExpandedSubBlockEnd.gif            }
 
InBlock.gif            
set 
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif
InBlock.gif                ViewState[TargetFrameKey] 
= value; 
ExpandedSubBlockEnd.gif            }
 
ExpandedSubBlockEnd.gif        }

InBlock.gif        [
InBlock.gif        NotifyParentProperty(
true), 
InBlock.gif        Bindable(
true),
InBlock.gif        Category(
"Appearance"),
InBlock.gif        DefaultValue(
"")
InBlock.gif        ]
InBlock.gif        
public string TargetFeatures 
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif
InBlock.gif            
get 
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif
InBlock.gif                
object o = ViewState[TargetFeaturesKey];
InBlock.gif                
return (o == null)?string.Empty:(string)o;
ExpandedSubBlockEnd.gif            }
 
InBlock.gif            
set 
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif
InBlock.gif                ViewState[TargetFeaturesKey] 
= value; 
ExpandedSubBlockEnd.gif            }
 
ExpandedSubBlockEnd.gif        }

InBlock.gif        [
InBlock.gif        DefaultValue(
true),
InBlock.gif        NotifyParentProperty(
true), 
InBlock.gif        ]
InBlock.gif        
public bool Replace 
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif
InBlock.gif            
get 
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif
InBlock.gif                
object o = ViewState[ReplaceKey];
InBlock.gif                
return (o == null)?true:(bool)o;
ExpandedSubBlockEnd.gif            }
 
InBlock.gif            
set 
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif
InBlock.gif                ViewState[ReplaceKey] 
= value; 
ExpandedSubBlockEnd.gif            }
 
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif        
#endregion

ContractedSubBlock.gifExpandedSubBlockStart.gif        
copy merge#region copy merge
InBlock.gif        [EditorBrowsable(EditorBrowsableState.Never)]
InBlock.gif        
public virtual void CopyFrom(WinPopItem s)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{    
InBlock.gif            
base.CopyFrom(s);
ExpandedSubBlockEnd.gif        }

InBlock.gif        [EditorBrowsable(EditorBrowsableState.Never)]
InBlock.gif        
public virtual void MergeWith(WinPopItem s)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
base.MergeWith(s);
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif        
#endregion

ContractedSubBlock.gifExpandedSubBlockStart.gif        
prerender#region prerender
InBlock.gif        [EditorBrowsable(EditorBrowsableState.Never)]
InBlock.gif        
public virtual string GetPreRenderJScript()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif
//            window.open(url, target, features, replace);
InBlock.gif
            return string.Format("window.open({0},{1},{2},{3})",new object[]
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    RenderHelper.StrToJavaPara(
this.TargetUrl),
InBlock.gif                    RenderHelper.StrToJavaPara(
this.TargetFrame),
InBlock.gif                    RenderHelper.StrToJavaPara(
this.TargetFeatures),
InBlock.gif                    RenderHelper.BoolToJavaPara(
this.Replace)
ExpandedSubBlockEnd.gif                }
+ ";\n\r";
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif        
#endregion

ContractedSubBlock.gifExpandedSubBlockStart.gif        
load from table#region load from table
InBlock.gif        
public virtual void LoadFromDataRow(System.Data.DataRow row)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            System.Data.DataTable table 
= row.Table;
InBlock.gif
InBlock.gif            
if(table.Columns.Contains("TargetURL"))
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
this.TargetUrl = (string)row["TargetURL"];
ExpandedSubBlockEnd.gif            }

InBlock.gif            
if(table.Columns.Contains("TargetFrame"))
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
this.TargetFrame = (string)row["TargetFrame"];
ExpandedSubBlockEnd.gif            }

InBlock.gif            
if(table.Columns.Contains("TargetFeatures"))
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
this.TargetFeatures = (string)row["TargetFeatures"];
ExpandedSubBlockEnd.gif            }

InBlock.gif            
if(table.Columns.Contains("Replace"))
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
this.Replace = (bool)row["Replace"];
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif        
#endregion

ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

None.gif
WinPopItem的实现比较简单,只是在基类上增加了一些自定义属性,并且增加一个GetPreRenderJScript() 函数用来用属性生成前台的jscript程序字符串。而LoadFromDataRow则用来从一个tablerow中加载属性。

以下是WinPopItemCollection的源代码
None.gif using  System;
None.gif
using  System.Web.UI;
None.gif
using  System.Web.UI.WebControls;
None.gif
using  System.Web.UI.Design;
None.gif
using  System.Drawing.Design;
None.gif
using  System.Drawing;
None.gif
using  System.Collections;
None.gif
using  System.ComponentModel;
None.gif
using  System.ComponentModel.Design;
None.gif
None.gif
namespace  Keyss.WebControls
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    [ 
InBlock.gif    PersistenceMode(PersistenceMode.InnerProperty),
InBlock.gif    ] 
InBlock.gif    
public class WinPopItemCollection:ViewStatePartCollectionBase
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif
InBlock.gif        
public int Add(WinPopItem item)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
return base.AddItem(item);
ExpandedSubBlockEnd.gif        }

InBlock.gif        
public WinPopItem this[int index]
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
get 
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
if(index >= Count || index < 0)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    
return null;
ExpandedSubBlockEnd.gif                }

InBlock.gif                
return (WinPopItem)this.InnerList[index];
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif        
protected override ViewStatePartBase NewItem()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
return new WinPopItem();
ExpandedSubBlockEnd.gif        }

InBlock.gif
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

None.gif
WinPopItemCollection的实现了集合的Add方法,当页面解析时将调用此方法从设计时的Tag标记装载Items ,并且定义了一个索引器,另外还重载了基类中的NewItem用来返回WinPopItem类型。

最后是WinPop组件的实现
None.gif using  System;
None.gif
using  System.Web.UI;
None.gif
using  System.Web.UI.WebControls;
None.gif
using  System.ComponentModel;
None.gif
None.gif
namespace  Keyss.WebControls
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    [DefaultProperty(
"Items"), 
InBlock.gif        ToolboxData(
"<{0}:WinPop runat=server></{0}:WinPop>")]
InBlock.gif    
public class WinPop : System.Web.UI.WebControls.WebControl
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
ContractedSubBlock.gifExpandedSubBlockStart.gif        
loaddata from table#region loaddata from table
InBlock.gif        
public virtual void LoadFromTable(System.Data.DataTable table)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
try
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
this.Items.Clear();
InBlock.gif                
foreach(System.Data.DataRow row in table.Rows)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    Keyss.WebControls.WinPopItem item 
= new Keyss.WebControls.WinPopItem();
InBlock.gif                    item.LoadFromDataRow(row);
InBlock.gif                    
this.Items.Add(item);
ExpandedSubBlockEnd.gif                }

ExpandedSubBlockEnd.gif            }

InBlock.gif            
catch
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
throw new ArgumentException("Table or filed name error!",table.TableName);
ExpandedSubBlockEnd.gif            }

InBlock.gif
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif        
#endregion

ContractedSubBlock.gifExpandedSubBlockStart.gif        
items#region items
InBlock.gif        
private WinPopItemCollection _items;
InBlock.gif        [
InBlock.gif        NotifyParentProperty(
true),
InBlock.gif        PersistenceMode(PersistenceMode.InnerProperty),
InBlock.gif        DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
InBlock.gif        ]
InBlock.gif        
public WinPopItemCollection Items
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
get 
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
if(this._items ==null
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    _items 
= new WinPopItemCollection();
InBlock.gif                    
if(this.IsTrackingViewState)
InBlock.gif                        _items.TrackViewState();
ExpandedSubBlockEnd.gif                }

InBlock.gif                
return _items;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif        
#endregion

ContractedSubBlock.gifExpandedSubBlockStart.gif        
render#region render
InBlock.gif        
protected override void OnPreRender(EventArgs e)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{    
InBlock.gif            System.Text.StringBuilder codesource 
= new System.Text.StringBuilder();
InBlock.gif            
if((this.Enabled)&&(!this.Items.IsEmpty)&&(!Page.IsStartupScriptRegistered(this.ClientID)))
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                codesource.Append(
"<script language=\"JavaScript\" >");
InBlock.gif                codesource.Append(
"\n\r");
InBlock.gif                
for(int i=0;i<Items.Count;i++)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    codesource.Append(Items[i].GetPreRenderJScript());
ExpandedSubBlockEnd.gif                }

InBlock.gif                codesource.Append(
"</script>");
InBlock.gif                Page.RegisterStartupScript(ClientID,codesource.ToString());
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif        
protected override void Render(HtmlTextWriter writer)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
if((this.Site!=null)&&this.Site.DesignMode)
InBlock.gif                writer.WriteLine(
this.ID);
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif        
#endregion

ContractedSubBlock.gifExpandedSubBlockStart.gif        
view State#region view State
InBlock.gif        
protected override void LoadViewState(object state)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
if(state !=null)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
object[] savedState = (object[])state;
InBlock.gif                
if(savedState[0!= null)
InBlock.gif                    
base.LoadViewState(savedState[0]);
InBlock.gif                
if(savedState[1!= null)
InBlock.gif                    Items.LoadViewState(savedState[
1]);
ExpandedSubBlockEnd.gif            }
    
InBlock.gif
ExpandedSubBlockEnd.gif        }

InBlock.gif        
protected override object SaveViewState()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
object[] savedState = new object[2];
InBlock.gif            savedState[
0= base.SaveViewState ();
InBlock.gif            savedState[
1= Items.SaveViewState();
InBlock.gif            
for(int i=0;i<savedState.Length;i++)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
if(savedState[i] != null)
InBlock.gif                    
return savedState;
ExpandedSubBlockEnd.gif            }

InBlock.gif            
return null;
ExpandedSubBlockEnd.gif        }

InBlock.gif        
protected override void TrackViewState()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
base.TrackViewState();
InBlock.gif            Items.TrackViewState();
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif        
#endregion

ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

None.gif

从源程序中可以看到WinPop中含有一个默认属性Items并且重载了基类中的视图状态函数,用来支持Items的视图状态。为了加载方便还实现了LoadFromTable方法用来从datatable中载入Items数据。由于WinPop并没有实际的HTML元素,只是在页面中注册jscript角本,所以重载的Render方法只是判断是否为设计时,如果是则输出控件的ID便于设计时选择该控件,而在OnPreRender方法中则注册startup类型的jscript块,这样当页面绘制时,控件会根据Items中的内容绘制一系列的window.open(url, target, features, replace);来实现弹出窗口的目的。

转载于:https://www.cnblogs.com/keyss/archive/2005/01/08/88608.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值