艾伟:控件之ViewState

简介: 主题,控件的viewstate状态一“七七八八”有次,朋友开玩笑说,不知道什么时候,微软会取消viewstate,不再使用隐藏字段在服务器与客户端保存状态!虽然,可以使用客户端技术减少一些回传,但是,一些必要的服务器状态还是要保存的,现在网络带宽已经不是问题,所以在网络上适当的传递一些状态数据,还...

主题,控件的viewstate状态

一“七七八八”

有次,朋友开玩笑说,不知道什么时候,微软会取消viewstate,不再使用隐藏字段在服务器与客户端保存状态!虽然,可以使用客户端技术减少一些回传,但是,一些必要的服务器状态还是要保存的,现在网络带宽已经不是问题,所以在网络上适当的传递一些状态数据,还是可以容忍的!当然,如果终端是mobile,可以考虑把viewstate保存到服务器上!

二“误解viewstate”

    园子里,有不少描写viewstate的文字,也看了不少,知道Viewstate实现了IStateManager接口的一个属性和三个方法!刚接触“她”的时候,一直以为control对象直接实现了IStateManager接口,模糊的记得好象有几个LoadViewstate和SaveViewstate方法,也没有在意方法有没有override修饰!后来发现不是这样的,control并没有直接实现IStateManager接口,而是通过定义一个StateBar类型的Viewstate属性,委托Viewstate属性去管理状态,也就是让StateBar类型去真正实现状态的管理,这种方式可以使控件本身和viewState的实现完全分离!也许,这些经验,对高手谈不上是“经验”,希望刚入门的同仁能少走点弯路!

三“结合Style样式,浅谈Viewstate”

Viewstate属性能装载的数据类型比较有限,但是有些不能加载的类型怎么办呢?当然是重写
IStateManager了,然后WebControl委托给ControlStyle属性来管理状态,有点象WebControl
定义ViewState属性

还是从简单的入手吧,直接使用Style类型的状态管理
目标,定义一个文本框和一个按钮的复合控件
要点,分别给文本框和按钮各自定义样式,并提升她们为顶级样式属性
图一

图二 (文本框和按钮的样式)

图四 Demo
Code
using System;
using
 System.Web.UI;
using
 System.Web.UI.WebControls;
using
 System.ComponentModel;
using
 System.ComponentModel.Design;

namespace
 WebControlLibrary
{
    [
    DefaultEvent(
"Button"
),
    DefaultProperty(
"Text"
),
    
//Designer(typeof(WebControlLibrary.Design.CustomerControlDesigner))

    ]
    
    
public class
 WebCustomControl1 : CompositeControl
    
{
        
//声明变量

        private Button _button;
        
private
 TextBox _textBox;
        
private static readonly object EventButtonClick = new object
();
        
private
 Style _buttonStyle;
        
private
 Style _textBoxStyle;

        
//定义属性Text,用于指定按钮上的文字

        [
        Bindable(
true
),
        Category(
"Appearance"
),
        DefaultValue(
""
),
        Description(
"获取或设置显示显示在按钮上的文字"
)
        ]
        
public string
 Text
        
{
            
get

            
{
                EnsureChildControls();
                
return
 _button.Text;
            }


            
set
            
{
                EnsureChildControls();
                _button.Text 
=
 value;
            }

        }


        
//定义ButtonStyle属性
        [
        Category(
"Style"
),
        Description(
"设置Button的样式属性"
),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
        NotifyParentProperty(
true
),
        PersistenceMode(PersistenceMode.InnerProperty),
        ]
        
public virtual
 Style ButtonStyle
        
{
            
get

            
{
                
if (_buttonStyle == null
)
                
{
                    _buttonStyle 
= new
 Style();
                    
if
 (IsTrackingViewState)
                    
{
                        ((IStateManager)_buttonStyle).TrackViewState();
                    }

                }

                
return _buttonStyle;
            }

        }


        
//定义TextStyle属性
        [
        Category(
"Style"
),
        Description(
"设置TextBox的样式属性"
),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
        NotifyParentProperty(
true
),
        PersistenceMode(PersistenceMode.InnerProperty),
        ]
        
public virtual
 Style TextBoxStyle
        
{
            
get

            
{
                
if (_textBoxStyle == null
)
                
{
                    _textBoxStyle 
= new
 Style();
                    
if
 (IsTrackingViewState)
                    
{
                        ((IStateManager)_textBoxStyle).TrackViewState();
                    }

                }

                
return _textBoxStyle;
            }

        }


        
//重写Controls属性
        public override ControlCollection Controls
        
{
            
get

            
{
                EnsureChildControls();
                
return base
.Controls;
            }

        }


        
//重写CreateChildControls方法,将子控件添加到复合控件中
        protected override void CreateChildControls()
        
{
            Controls.Clear();
            _button 
= new
 Button();
            _textBox 
= new
 TextBox();
            _button.ID 
= "btn"
;
            _button.CommandName 
= "ButtonClick"
;
            
this
.Controls.Add(_button);
            
this
.Controls.Add(_textBox);
        }


        
//重写Render方法,呈现控件中其他的HTML代码
        protected override void Render(HtmlTextWriter output)
        
{
            
//AddAttributesToRender(output);

            if (_textBoxStyle != null)
            
{
                _textBox.ApplyStyle(TextBoxStyle);
            }

            
if (_buttonStyle != null)
            
{
                _button.ApplyStyle(ButtonStyle);
            }

            output.AddAttribute(HtmlTextWriterAttribute.Border, 
"0px");
            output.AddAttribute(HtmlTextWriterAttribute.Cellpadding, 
"5px"
);
            output.AddAttribute(HtmlTextWriterAttribute.Cellspacing, 
"0px"
);
            output.RenderBeginTag(HtmlTextWriterTag.Table);
            output.RenderBeginTag(HtmlTextWriterTag.Tr);
            output.RenderBeginTag(HtmlTextWriterTag.Td);
            _textBox.RenderControl(output);
            output.RenderEndTag();
            output.RenderBeginTag(HtmlTextWriterTag.Td);
            _button.RenderControl(output);
            output.RenderEndTag();
            output.RenderEndTag();
            output.RenderEndTag();
        }


        
//事件处理
        public event EventHandler ButtonClick
        
{
            add
            
{
                Events.AddHandler(EventButtonClick, value);
            }

            remove
            
{
                Events.RemoveHandler(EventButtonClick, value);
            }

        }


        
protected virtual void OnButtonClick(EventArgs e)
        
{
            EventHandler buttonClickHandler 
=
 (EventHandler)Events[EventButtonClick];
            
if (buttonClickHandler != null
)
            
{
                buttonClickHandler(
this
, e);
            }

        }


        
protected override bool OnBubbleEvent(object sender, EventArgs e)
        
{
            
bool handled = false
;
            
if (e is
 CommandEventArgs)
            
{
                CommandEventArgs ce 
=
 (CommandEventArgs)e;
                
if (ce.CommandName == "ButtonClick"
)
                
{
                    OnButtonClick(EventArgs.Empty);
                    handled 
= true
;
                }

            }

            
return handled;
        }


        
//样式状态管理,重写3个相关方法
        protected override void LoadViewState(object savedState)
        
{
            
if (savedState == null
)
            
{
                
base.LoadViewState(null
);
                
return
;
            }

            
if (savedState != null)
            
{
                
object[] myState = (object
[])savedState;
                
if (myState.Length != 3
)
                
{
                    
throw new ArgumentException("无效的ViewState"
);
                }

                
base.LoadViewState(myState[0]);
                
if (myState[1!= null
)
                
{
                    ((IStateManager)TextBoxStyle).LoadViewState(myState[
1
]);
                }

                
if (myState[2!= null)
                
{
                    ((IStateManager)ButtonStyle).LoadViewState(myState[
2
]);
                }

            }

        }


        
protected override object SaveViewState()
        
{
            
object[] myState = new object[3
];
            myState[
0= base
.SaveViewState();
            myState[
1= (_textBoxStyle != null? ((IStateManager)_textBoxStyle).SaveViewState() : null
;
            myState[
2= (_buttonStyle != null? ((IStateManager)_buttonStyle).SaveViewState() : null
;

            
for (int i = 0; i < 3; i++
)
            
{
                
if (myState[i] != null
)
                
{
                    
return
 myState;
                }

            }

            
return null;
        }


        
protected override void TrackViewState()
        
{
            
base
.TrackViewState();

            
if (_buttonStyle != null
)
            
{
                ((IStateManager)_buttonStyle).TrackViewState();
            }

            
if (_textBoxStyle != null)
            
{
                ((IStateManager)_textBoxStyle).TrackViewState();
            }

        }

    }

}

Demo比较简单,在类顶部定义了两个Style类型的属性,然后重写维护状态的三个方法一个属性
注意
1.这里并不是直接重写IStateManager接口
2.重写 SaveViewState 方法以将附加样式属性保存到
ViewState
3.重写 LoadViewState 方法以自定义从 ViewState 的附加样式属性的还原
4.必须以添加它们的相同顺序检索
四 控件状态的细节远不只是这些,有不妥当的地方,还望同仁指出...(后续)
目录
相关文章
|
Web App开发 前端开发 JavaScript
SAP UI5 控件库里 Form 控件和 SimpleForm 控件的区别和联系讲解试读版
SAP UI5 控件库里 Form 控件和 SimpleForm 控件的区别和联系讲解试读版
如何解决WPF中 ScrollViewer 内包含 TreeView 或者 ListBox 等控件时滚轮事件被劫持的问题
如何解决WPF中 ScrollViewer 内包含 TreeView 或者 ListBox 等控件时滚轮事件被劫持的问题
|
Web App开发
艾伟:WinForm控件开发总结(三)------认识WinForm控件常用的Attribute
在前面的文章里我们制作了一个非常简单的控件。现在我们回过头来看看这些代码透露出什么信息。   这个类是直接从Control类派生出来的,自定义控件都是直接从Control类派生出来的。这个类定义了一个属性TextAlignment,用来控制文本在控件中显示的位置:           ...
1008 0
|
Web App开发
艾伟:WinForm控件开发总结(四)-----控件属性的串行化
前一篇文章介绍了常用的设计时Attribute。其中BrowsableAttribute,CategoryAttribute,DescriptionAttribute,DefaultPropertyAttribute,DefaultEventAttribute都是比较简单的,也是可有可无,但是为了提供更好的用户体验这些Attribute最好不要省掉,如果你对这些Attribute还不熟悉,可以参考我前一篇文章的描述或者查看MSDN,这里我就不在赘述了。
953 0
|
Web App开发
艾伟:WinForm控件开发总结(五)-----为控件的复杂属性提供类型转换器
上一篇文章我已经介绍了TypeConverterAttribute元数据的作用,本文将通过代码向你展示具体的实现。在这个例子中,我要给控件添加一个复杂的属性,这个属性对这个控件没有什么功用,纯粹是为了演示,有些牵强附会了。
817 0
|
C# Windows
艾伟_转载:C# WinForm开发系列 - TextBox
包含金额/日期输入框,带弹出数字面板的计算输入框,安全密码输入等控件(文章及相关代码搜集自网络,仅供参考学习,版权属于原作者! ).   1.CalculatorBox    CalculatorBox.
1376 0