在缓存中保存控件(ASP面板和子项)状态

时间:2012-06-13 14:27:51

标签: asp.net caching viewstate

我正在寻找一种简单易用的方法来缓存用户的过滤器设置。我最初的想法是覆盖包含我的过滤器控件的面板的保存/加载ViewState进程,并在那里保存/加载控件状态。我找不到办法做到这一点。

这是否可以在不改变整个控件,页面或站点的状态过程的情况下实现?

1 个答案:

答案 0 :(得分:0)

这似乎是一个有趣的案例,所以我已经尝试了一个解决方案来完成这个功能。我已经提出了下面的代码,这应该是一个良好的开端。它仅适用于控件的“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);
            }
        }
    }
}