我正在寻找一种简单且可扩展的方式来为用户缓存过滤器设置。我最初的想法是覆盖包含我的过滤器控件的面板的保存/加载 ViewState 进程并在那里保存/加载控件状态。我还没有找到一种方法来做到这一点。
这是否可能在不改变整个控件、页面或站点的状态过程的情况下实现?
这似乎是一个有趣的案例,所以我尝试了一个解决方案来完成这个功能。我想出了下面的代码,这应该是一个好的开始。它仅适用于控件的“DefaultProperty”,但通过添加对特定控件类型的检查,您可以缓存和设置您喜欢的任何属性。
此外,它仅在第一次加载页面时使用缓存值设置控件。不确定您是否希望控件的值在回发之间更改以反映另一个用户/会话是否进行了更改。
using System.Collections.Generic;
using System.ComponentModel;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public class CachedStatePanel : Panel
{
private static Dictionary<string, object> CachedFilters
{
get
{
if (HttpContext.Current.Cache["CachedFilters"] == null)
{
HttpContext.Current.Cache["CachedFilters"] = new Dictionary<string, object>();
}
return (Dictionary<string, object>)HttpContext.Current.Cache["CachedFilters"];
}
}
protected override void CreateChildControls()
{
base.CreateChildControls();
if (!Page.IsPostBack)
{
foreach (Control child in Controls)
{
SetFromCacheRecursive(child);
}
}
}
protected override object SaveViewState()
{
var state = base.SaveViewState();
if (Page.IsPostBack)
{
foreach (Control child in Controls)
{
LoadCachedStateRecursive(child);
}
}
return state;
}
private static void LoadCachedStateRecursive(Control current)
{
if ((current == null) || (current.ID == null)) return;
var attribs = current.GetType().GetCustomAttributes(typeof(DefaultPropertyAttribute), true);
if ((attribs != null) && (attribs.Length > 0))
{
var propName = ((DefaultPropertyAttribute)attribs[0]).Name;
var prop = current.GetType().GetProperty(propName);
if (prop != null)
{
CachedFilters[current.ID] = prop.GetValue(current, null);
}
}
if (current.HasControls())
{
foreach (Control child in current.Controls)
{
LoadCachedStateRecursive(child);
}
}
}
private static void SetFromCacheRecursive(Control current)
{
if ((current == null) || (current.ID == null) || (!CachedFilters.ContainsKey(current.ID))) return;
var attribs = current.GetType().GetCustomAttributes(typeof(DefaultPropertyAttribute), true);
if ((attribs != null) && (attribs.Length > 0))
{
var propName = ((DefaultPropertyAttribute)attribs[0]).Name;
var prop = current.GetType().GetProperty(propName);
if (prop != null)
{
prop.SetValue(current, CachedFilters[current.ID], null);
}
}
if (current.HasControls())
{
foreach (Control child in current.Controls)
{
SetFromCacheRecursive(child);
}
}
}
}