使用控制管理器减少递归Page.FindControl的使用 - 不确定这是否可行?

时间:2011-06-15 17:09:14

标签: c# asp.net

我在Web信息中心上动态添加和重新创建控件。我一直试图减少我对Page.FindControl的使用;我发现在页面上有大量动态创建的内容会很慢。

在我的尝试中,我创建了一个RegenerationManager单例,现在负责重新生成我的动态内容。每当它重新生成一个对象时,它就会将该对象存储在一个列表中。该管理器根据对象类型保留其中几个列表。

稍后,当我需要通过ID获取对象时,我会转到我的再生管理器来检索该对象。

E.G:

public class RegenerationManager
{
    private static readonly ILog Logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);

    private static readonly RegenerationManager instance = new RegenerationManager();
    private RegenerationManager() { }

    public static RegenerationManager Instance
    {
        get { return instance; }
    }

    public List<CormantRadPane> RegeneratedPanes = new List<CormantRadPane>();
    public List<CormantRadDockZone> RegeneratedDockZones = new List<CormantRadDockZone>();

    /// <summary>
    /// Recreates all the dynamically made DockZones.
    /// </summary>
    public void RegenerateDockZones()
    {
        Logger.Info("Regenerating dock zones.");
        foreach (KeyValuePair<string, RadDockZoneSetting> dockZoneState in RadControlManager.GetStates<SerializableDictionary<string, RadDockZoneSetting>>())
        {
            try
            {
                RadDockZoneSetting dockZoneSetting = dockZoneState.Value as RadDockZoneSetting;
                Logger.Info(String.Format("Loading state data for dock zone with setting ID: {0}", dockZoneSetting.ID));
                CormantRadDockZone dockZone = new CormantRadDockZone(dockZoneSetting);
                RegeneratedDockZones.Add(dockZone);
                CormantRadPane pane = RegeneratedPanes.First(regeneratedPane => regeneratedPane.ID == dockZoneSetting.ParentID);
                pane.Controls.Add(dockZone);
            }
            catch (Exception exception)
            {
                Logger.ErrorFormat("Error regenerating dock zones. Reason: {0}", exception.Message);
            }
        }
    }
}

/// <summary>
/// Creates the RadDock + Contents when dropping a graph onto the page.
/// </summary>
/// <param name="sender"> The RadListBox with an element being dropped from inside it. </param>
/// <param name="e"> Information about the drop such as target and what is being dropped. </param>
protected void RadListBox_Dropped(object sender, RadListBoxDroppedEventArgs e)
{
    CormantRadDockZone dockZoneOld = Utilities.FindControlRecursive(Page, e.HtmlElementID) as CormantRadDockZone;
    CormantRadDockZone dockZone = RegenerationManager.Instance.RegeneratedDockZones.First(regeneratedDockZone => regeneratedDockZone.ID == e.HtmlElementID);

    if (!object.Equals(dockZone, null) && !dockZone.Docks.Any())
    {
        RadSlidingPane slidingPane = ((sender as RadListBox).Parent as RadSlidingPane);
        CormantReport report = new CormantReport(int.Parse(e.SourceDragItems[0].Value), e.SourceDragItems[0].Text, slidingPane.Title);
        CormantRadDock dock = new CormantRadDock(report);
        dock.CreateContent();
        dockZone.Controls.Add(dock);
    }
}

现在,我认为这是一个非常好的解决方案,但经过测试,我发现添加到dockZone的CormantRadDock没有显示在我的网络仪表板上,但是如果我将它添加到dockZoneOld那就是它。

看看这两个对象,我没有注意到这两个对象有什么不同,但显然有一些东西。

我的想法是否可以实施?

编辑:我怀疑问题出在Telerik的控件上。我有个想法,我会稍微报告一下。 编辑:这确实是一个Telerik的事情。我需要浏览他们的RadDockLayout.RegisteredDockZone列表,而不是保留我自己的托管列表。

1 个答案:

答案 0 :(得分:0)

这里要做的关键是调试你的代码并在这一行上设置一个断点:

CormantRadDockZone dockZone = RegenerationManager.Instance.RegeneratedDockZones.First(regeneratedDockZone =>regeneratedDockZone.ID == e.HtmlElementID);`

然后对RegenerationManager.Instance.RegeneratedDockZones的内容进行快速监视,看看该列表中是否包含任何元素。所以我们在这里检查基础知识 - 列表中是否包含任何项目?

如果有项目,你需要弄清楚为什么你要查找的特定元素不在列表中。该列表必须正常工作,因为其中有项目,但尚未添加此特定元素。

如果您100%将元素添加到列表中,那么它可能与您使用的单例模式有关。老实说,它看起来不错,但我不是单身设计模式的专家。

抱歉,我无法提供更多帮助。

编辑:

可能有所帮助的一点是重构一下课程:

private IList<CormantRadPane> _regeneratedPanes;
private IList<CormantRadDockZone> _regeneratedDockZones;

    public IList<CormantRadPane>  RegeneratedPanes
    {
        get
        {
        if(_regeneratedPanes == null)
                {
                    _regeneratedPanes = new List<CormantRadPane>()
                }

                return _regeneratedPanes
            }
        }

        public IList<CormantRadDockZone> RegeneratedDockZones
        {
            get
            {
                if(_regeneratedDockZones == null)
                {
                    _regeneratedDockZones = new List<CormantRadDockZone>()
                }

                return _regeneratedDockZones
            }
        }

这里我使用属性返回列表,而不是让人们直接访问列表成员。

这可以帮助您调试代码。