自定义SharePoint CheckBoxList提交后Items为空的技术求助
解决自定义ListItemCollection回发后Items为空的问题
首先,咱们得搞清楚问题根源:当你自定义ListItemCollection(也就是你的DialogFieldItemCollection)时,ASP.NET默认的控件状态管理(ViewState)机制没办法自动识别并处理这个自定义集合,所以回发时控件没法从ViewState里恢复Items数据,就导致Items为空了。下面是具体的解决步骤和代码示例:
1. 确保自定义ListItem正确保存自定义属性到ViewState
如果你的集合里是自定义的ListItem(比如DialogFieldItem),首先要让它把自定义属性存入ViewState,这样状态才能被持久化:
public class DialogFieldItem : ListItem { // 自定义属性,用ViewState存储 public string CustomProperty { get => (string)ViewState["CustomProperty"] ?? string.Empty; set => ViewState["CustomProperty"] = value; } }
2. 让自定义ListItemCollection实现IStateManager接口
ASP.NET的ViewState管理依赖IStateManager接口来保存和恢复状态,所以你的DialogFieldItemCollection必须实现这个接口,才能让集合里的所有Item状态被正确跟踪:
public class DialogFieldItemCollection : ListItemCollection, IStateManager { private readonly StateBag _viewState = new StateBag(); private bool _isTrackingViewState; public DialogFieldItemCollection(ListControl owner) : base(owner) { } #region IStateManager实现 public bool IsTrackingViewState => _isTrackingViewState; public void TrackViewState() { _isTrackingViewState = true; // 跟踪每个ListItem的状态 foreach (DialogFieldItem item in this) { ((IStateManager)item).TrackViewState(); } _viewState.TrackViewState(); } public object SaveViewState() { // 保存集合本身的状态和每个Item的状态 var state = new object[Count + 1]; state[0] = _viewState.SaveViewState(); for (int i = 0; i < Count; i++) { state[i + 1] = ((IStateManager)this[i]).SaveViewState(); } return state; } public void LoadViewState(object savedState) { if (savedState == null) return; var state = (object[])savedState; // 恢复集合和每个Item的状态 _viewState.LoadViewState(state[0]); for (int i = 0; i < Count; i++) { ((IStateManager)this[i]).LoadViewState(state[i + 1]); } } #endregion }
3. 自定义CheckBoxList控件,重写Items属性和状态管理方法
接下来,你的自定义CheckBoxList需要重写Items属性,返回你的DialogFieldItemCollection,同时重写状态相关方法,确保集合状态被正确处理:
public class CustomCheckBoxList : CheckBoxList { private DialogFieldItemCollection _items; // 重写Items属性,返回自定义集合 public new DialogFieldItemCollection Items { get { if (_items == null) { _items = new DialogFieldItemCollection(this); if (IsTrackingViewState) { ((IStateManager)_items).TrackViewState(); } } return _items; } } protected override void TrackViewState() { base.TrackViewState(); // 开始跟踪自定义集合的状态 ((IStateManager)_items).TrackViewState(); } protected override object SaveViewState() { // 合并基础控件状态和自定义集合状态 var baseState = base.SaveViewState(); var itemsState = ((IStateManager)_items).SaveViewState(); return new object[] { baseState, itemsState }; } protected override void LoadViewState(object savedState) { if (savedState == null) { base.LoadViewState(null); return; } // 拆分并恢复基础状态和集合状态 var stateArray = (object[])savedState; base.LoadViewState(stateArray[0]); ((IStateManager)_items).LoadViewState(stateArray[1]); } }
4. 回发时避免重复绑定数据
最后,在页面或WebPart的代码里,只有在非回发时才绑定数据,否则回发时重新绑定会覆盖ViewState恢复的Items:
protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { // 首次加载时绑定自定义Items var checkBoxList = (CustomCheckBoxList)FindControl("YourCustomCheckBoxList"); checkBoxList.Items.Add(new DialogFieldItem { Text = "选项1", Value = "1", CustomProperty = "自定义值1" }); checkBoxList.Items.Add(new DialogFieldItem { Text = "选项2", Value = "2", CustomProperty = "自定义值2" }); } }
关键注意点
- 确保控件的
EnableViewState属性为true(默认是true,但若被手动设置为false会导致状态丢失)。 - 自定义ListItem必须继承自
System.Web.UI.WebControls.ListItem,因为它已经实现了IStateManager接口,能自动处理基础状态。
内容的提问来源于stack exchange,提问作者Emaborsa
相关产品推荐
相关产品推荐

