asp.net 動態創建TextBox控件 如何加載狀態信息


接着上文Asp.net TextBox的TextChanged事件你真的清楚嗎? 這里我們來說說狀態數據時如何加載的。
雖然在Control中有調用狀態轉存的方法,但是這里有一個判斷條件 if (_controlState >= ControlState.ViewStateLoaded)  一般的get請求這里的條件是不滿足的。

internal enum ControlState
{
    Constructed,
    FrameworkInitialized,
    ChildrenInitialized,
    Initialized,
    ViewStateLoaded,

    Loaded,
    PreRendered
}

我們知道在page的ProcessRequest中this.ControlState = ControlState.FrameworkInitialized; ProcessRequestMain方法中在Init后有調用this.InitRecursive(null);在這個方法里面有這么一句_controlState = ControlState.Initialized;,在LoadAllState()方法中有這么一句 base.LoadViewStateRecursive(second.Second);,而LoadViewStateRecursive中又有_controlState = ControlState.ViewStateLoaded這句帶代碼,所以我們在Page_load中動態條件控件時, if (_controlState >= ControlState.ViewStateLoaded)條件成立,如圖:

所以在運行this.form1.Controls.Add(txt);這句以前,txt的值為demo1,

如圖


但是運行以后之就發生變化了:

當然這里的txt.Text值也是我上次post過來的舊值,新值是在控件的LoadPostData方法中重新綁定。在默認的LoadViewStateRecursive方法中有一個很重要的判斷

        internal void LoadViewStateRecursive(object savedState) {
            // nothing to do if we have no state
            if (savedState == null || flags[disableViewState])
                return; 

。。。。。。。

_controlState = ControlState.ViewStateLoaded
            }

大家看到我上面是一個CustTextBoxt : TextBox控件,如果我們直接添加TextBox控件的話,那么着這里的txt.Text一直都是demo1,可見控件動態添加的時候是否加載狀態數 據與狀態數據的保存有關。而狀態數據的保存主要就是SaveViewState完成的,這里我第一次post的時候SaveViewState返回數據:

所以第二次能取到上次post過來的數據。

其中與SaveViewState有關的方法主要有:

public class TextBox : WebControl, IPostBackDataHandler, IEditableTextControl {
     protected override object SaveViewState() {
            if (SaveTextViewState == false) {
                ViewState.SetItemDirty("Text", false);
            }
            return base.SaveViewState();
        }
         private bool SaveTextViewState {
            get {
                //
 

                // Must be saved when
                // 1. There is a registered event handler for SelectedIndexChanged
                // 2. Control is not enabled or visible, because the browser's post data will not include this control
                // 3. The instance is a derived instance, which might be overriding the OnTextChanged method
 
                if (TextMode == TextBoxMode.Password) {
                    return false;
                }

                if ((Events[EventTextChanged] != null) ||
                    (IsEnabled == false) ||
                    (Visible == false) ||
                    (ReadOnly) ||
                    (this.GetType() != typeof(TextBox))) {
                    return true;
                }
 
                return false;
            }
        }
 
    }
 public class WebControl : Control, IAttributeAccessor {
      protected override object SaveViewState() {
            Pair myState = null;
 
            // Save values cached out of view state
            if (_webControlFlags[disabledDirty]) {
                ViewState["Enabled"] = !flags[isWebControlDisabled];
            }

            if (ControlStyleCreated) {
                // the style shares the StateBag of its owner WebControl
                // call SaveViewState to let style participate in state management
                ControlStyle.SaveViewState();
            }

            object baseState = base.SaveViewState();
            object aState = null;
            if (attrState != null) {
                aState = attrState.SaveViewState();
            }

            if (baseState != null || aState != null) {
                myState = new Pair(baseState, aState);
            }
            return myState;
        }
}
public class Control : IComponent, IParserAccessor, IUrlResolutionService, IDataBindingsAccessor, IControlBuilderAccessor, IControlDesignerAccessor, IExpressionsAccessor {
      protected virtual object SaveViewState() {
            // Save values cached out of view state
            if (flags[visibleDirty]) {
                ViewState["Visible"] = !flags[invisible];
            }
            if (flags[validateRequestModeDirty]) {
                ViewState["ValidateRequestMode"] = (int)ValidateRequestMode;
            }
            if (_viewState != null)
                return _viewState.SaveViewState();

            return null;
        }
}
public sealed class StateBag : IStateManager, IDictionary {
 internal object SaveViewState() {
            ArrayList data = null;
            if (bag.Count != 0) {
                IDictionaryEnumerator e = bag.GetEnumerator();
                while (e.MoveNext()) {
                    StateItem item = (StateItem)(e.Value);
                    if (item.IsDirty) {
                        if (data == null) {
                            data = new ArrayList();
                        }
#if OBJECTSTATEFORMATTER
                        data.Add(new IndexedString((string)e.Key));
#else
                        data.Add(e.Key);
#endif
                        data.Add(item.Value);
                    }
                }
            }

            return data;
        }
    }

到這里我們知道保存狀態信息主要是在StateBag SaveViewState方法中,這里有一個檢查  if (item.IsDirty) ,在TextBox的SaveViewState方法中有一個判斷

    if (SaveTextViewState == false) {
                ViewState.SetItemDirty("Text", false);
            } 

與它的SaveTextViewState 屬性有關。

那么我們可以總結一下:動態創建的控件默認是在被添加的時候加載器狀態數據,如果是靜態添加的數據那就是LoadAllState來處理狀態數據的加載。狀態數據的加載與控件的SaveViewState密切相關,如果該方法的返回值為null既沒有狀態信息,那也不需要加載什么狀態信息了


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM