我自己写了个控件,定义了一个DataTable属性,但是非常奇怪的是,不管该属性在自定义的控件内部
如何改变,都不能够在提交后取回,该如何实现IStateManager呢?
public DataTable CheckboxSelectedInfo
{
get
{
m_dtCheckboxSelectedInfo = (DataTable)this.ViewState[CHECKBOX_KEYNAME];
return m_dtCheckboxSelectedInfo;
}
set
{
m_dtCheckboxSelectedInfo = value;
ViewState[CHECKBOX_KEYNAME] = m_dtCheckboxSelectedInfo; 
ViewState.SetItemDirty(CHECKBOX_KEYNAME, true);
}
}

解决方案 »

  1.   

    我的IStateManager是按如下方式实现,可是还是不能取得CheckboxSelectedInfo的属性值。
    而且断点也无法进入下面的几个方法,请各位大侠多多指教!public class CallBackControl : System.Web.UI.WebControls.WebControl,IStateManager
    {
    bool  IStateManager.IsTrackingViewState
    {
    get 
    {
    return ((IStateManager)this.ViewState).IsTrackingViewState;
    }
    }
    /// <summary>
    /// This method saves the state for a particular menuitem.</summary>
    /// <res>This method returns a Triplet, where the first item is the result from the MenuItem's ViewState's
    /// SaveViewState() method call.  The second is the ViewState saved from the
    /// subItems MenuItemCollection instance.  The third item is the ViewState saved from the
    /// RolesCollection.
    /// </res>
    /// <returns>A Triplet containing the ViewState and state of the subitems.</returns>
    object IStateManager.SaveViewState()
    {
    if( (!((IDictionary)this.ViewState).Contains(CHECKBOX_KEYNAME)) || (this.ViewState.IsItemDirty(CHECKBOX_KEYNAME))) {
    {
    this.ViewState.Clear();
    // Add the _message property to the StateBag.
    this.ViewState.Add(CHECKBOX_KEYNAME, m_dtCheckboxSelectedInfo);
    }
    }
    return ((IStateManager)this.ViewState).SaveViewState(); } /// <summary>
    /// Loads the state upon postback back into the MenuItem.
    /// </summary>
    /// <param name="savedState">The state preserved from the SaveViewState() method in the
    /// previous page invocation.</param>
    void IStateManager.LoadViewState(object savedState)
    {
    m_dtCheckboxSelectedInfo = (DataTable)this.ViewState[CHECKBOX_KEYNAME];
    if (savedState != null)
    ((IStateManager)this.ViewState).LoadViewState(savedState);
    } /// <summary>
    /// Starts tracking view state for the ViewState and subItems properties.
    /// </summary>
    void IStateManager.TrackViewState()
    {
    base.TrackViewState();
    ((IStateManager)this.ViewState).TrackViewState();
    }
    }
      

  2.   

    这样的话,你完全没有必要去实现 IStateManager, 把 IStateManager 的代码去掉在试试
      

  3.   

    你的控件应该从DataTable继承下来,它就有那个功能了,不满意的话,可以自己重写父类的方法。
      

  4.   

    public class CallBackControl : System.Web.UI.WebControls.WebControl,IStateManager
    类的定义如上,去掉IStateManager也是一样的效果。
      

  5.   

    关于IStateManager的文章有谁可以推荐一下?
      

  6.   

    没仔细看,你debug的话,确定你的数据存到ViewState里去了么?LoadViewState有没有被执行呢?public class CallBackControl : System.Web.UI.WebControls.WebControl,INamingContainer ....
      

  7.   

    if you want to persist DataTable, you don't need implement IStateManager1. MyControls.cs:using System;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Data;namespace MyControls
    {
      public class MyTableControl : WebControl
      {
    public DataTable MyData
    {
    get
    {
    object o = ViewState["MyData"];
    return (DataTable)o;
    }
    set
    {
    ViewState["MyData"] = value;
    }
    }
      }
    }2. compile it into an assembly and copy it to the bin directory
    E:\labs\>csc /t:library MyControls.cs3. TestDataControls.aspx:
    <%@ Import Namespace="System.Data" %>
    <%@ Register TagPrefix="cc" Assembly="MyControls" Namespace="MyControls" %>
    <form runat="server">
    <cc:MyTableControl id="mc" runat="server" />
    <asp:Button id="btn" runat="server" Text="Click Me" OnClick="Button_Click" />
    </form>
    <script language="C#" runat="server">
    void Page_Load(Object sender, EventArgs e)
    {
    DataTable dt = mc.MyData;
    if (dt == null)
    {
    Response.Write("adding data<BR>");
    dt = new DataTable();
    dt.Columns.Add("Time", typeof(DateTime)); AddData(dt);
    mc.MyData = dt;
    } foreach (DataRow dr in dt.Rows)
    {
    Response.Write(dr["Time"] + "<BR>");
    }
    }void AddData(DataTable dt)
    {
      DataRow dr = dt.NewRow();
      dr["Time"] = DateTime.Now;
      dt.Rows.Add(dr);
    }void Button_Click(Object sender, EventArgs e)
    {
    DataTable dt = mc.MyData;
    AddData(dt);
    }
    </script>
      

  8.   

    TO:思归
    现在有如下几个问题,很让人疑惑。
    1)实现INamingContainer接口后,DataTable的属性值不再能够序列化??2)我上面的问题是在控件的Render方法中修改了DataTable中的记录行,但是修改部分不能够被viewstate记住,为什么??
     在stateBag中我确信指定键值对应的DataTable已经发生了改变,可为什么修改的部分无法序列化呢?3)IStateManager的几个方法何时被调用,为什么我在DEBUG时跟踪不到呢?如IStateManager.TrackViewState()
                                                
      

  9.   

    1. 
    public class MyTableControl : WebControl, INamingContainerstill works for me2. SaveViewState runs before Render, so it is too late to change state in Render3. you don't need to implement IStateManager if you derive from Control or WebControl
      

  10.   

    多谢各位参与,终于可以结贴了。
    1)msdn关于StateBag的说明如下
    “在控件处理生存期的任何阶段可以从此类读取,但是当控件正在呈现时不应该向此类写入。”2)WebControl中已经有了viewState属性,不需要再implement IStateManager 
    应该override IStateManager 的三个方法即可。有遇到相关问题的,可以发MAIL给我一起讨论。[email protected]