Сохранение состояния Динамические пользовательские элементы управления ... Помогите! - PullRequest
0 голосов
/ 12 января 2011

У меня есть страница с LinkButton, и при нажатии на нее я бы хотел добавить пользовательский контроль на страницу.Мне нужно иметь возможность добавлять / удалять столько элементов управления, сколько хотел бы пользователь.Пользовательский контроль состоит из трех выпадающих списков.В первом раскрывающемся списке свойство auotpostback имеет значение true и подключается к событию OnSelectedIndexChanged, которое при запуске загружает два оставшихся раскрывающихся списка с соответствующими значениями.

Моя проблема в том, где бы я ни помещал код в хостстраница, пользовательский контроль не загружается должным образом.Я знаю, что должен воссоздавать пользовательские элементы управления для каждой обратной передачи, и я создал метод, который выполняется в методе OnPreInit страниц хостинга.Я все еще получаю следующую ошибку: Невозможно изменить коллекцию элементов управления на этапах DataBind, Init, Load, PreRender или Unload.

Вот мой код: Спасибо !!!!

bool createAgain = false;
    IList<FilterOptionsCollectionView> OptionControls
    {
        get
        {
            if (SessionManager.Current["controls"] != null)
                return (IList<FilterOptionsCollectionView>)SessionManager.Current["controls"];
            else
                SessionManager.Current["controls"] = new List<FilterOptionsCollectionView>();
            return (IList<FilterOptionsCollectionView>)SessionManager.Current["controls"];
        }
        set
        {
            SessionManager.Current["controls"] = value;
        }
    }
    protected void Page_Load(object sender, EventArgs e)
    {
        Master.Page.Title = Title;
        LoadViewControls(Master.MainContent, Master.SideBar, Master.ToolBarContainer);
    }

    protected override void OnPreInit(EventArgs e)
    {
        base.OnPreInit(e);
        System.Web.UI.MasterPage m = Master;
        Control control = GetPostBackControl(this);
        if ((control != null && control.ClientID ==
                        (lbAddAndCondtion.ClientID) || createAgain))
        {
            createAgain = true;
            CreateUserControl(control.ID);
        }
    }

    protected void AddAndConditionClicked(object o, EventArgs e)
    {
        var control = LoadControl("~/Views/FilterOptionsCollectionView.ascx");
        OptionControls.Add((FilterOptionsCollectionView)control);
        control.ID = "options" + OptionControls.Count.ToString();
        phConditions.Controls.Add(control);
    }



    public event EventHandler<Insight.Presenters.PageViewArg> OnLoadData;



    private Control FindControlRecursive(Control root, string id)
    {
        if (root.ID == id)
        {
            return root;
        }
        foreach (Control c in root.Controls)
        {
            Control t = FindControlRecursive(c, id);
            if (t != null)
            {
                return t;
            }
        }
        return null;
    }

    protected Control GetPostBackControl(System.Web.UI.Page page)
    {
        Control control = null;
        string ctrlname = Page.Request.Params["__EVENTTARGET"];
        if (ctrlname != null && ctrlname != String.Empty)
        {
            control = FindControlRecursive(page, ctrlname.Split('$')[2]);
        }
        else
        {
            string ctrlStr = String.Empty;
            Control c = null;
            foreach (string ctl in Page.Request.Form)
            {
                if (ctl.EndsWith(".x") || ctl.EndsWith(".y"))
                {
                    ctrlStr = ctl.Substring(0, ctl.Length - 2);
                    c = page.FindControl(ctrlStr);
                }
                else
                {
                    c = page.FindControl(ctl);
                }
                if (c is System.Web.UI.WebControls.CheckBox ||
                c is System.Web.UI.WebControls.CheckBoxList)
                {
                    control = c;
                    break;
                }
            }
        }
        return control;
    }


    protected void CreateUserControl(string controlID)
    {
        try
        {
            if (createAgain && phConditions != null)
            {
                if (OptionControls.Count > 0)
                {
                    phConditions.Controls.Clear();
                    foreach (var c in OptionControls)
                    {
                        phConditions.Controls.Add(c);
                    }
                }
            }
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }

Вот код контроля пользователя:

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="FilterOptionsCollectionView.ascx.cs" Inherits="Insight.Website.Views.FilterOptionsCollectionView" %>

namespace Insight.Website.Views

{[ViewStateModeById] открытый частичный класс FilterOptionsCollectionView: System.Web.UI.UserControl {protected void Page_Load (отправитель объекта, EventArgs e) {

    }

    protected override void OnInit(EventArgs e)
    {
        LoadColumns();
        ddlColumns.SelectedIndexChanged += new RadComboBoxSelectedIndexChangedEventHandler(ColumnsSelectedIndexChanged);
        base.OnInit(e);
    }

    protected void ColumnsSelectedIndexChanged(object o, EventArgs e)
    {
        LoadCriteria();
    }

    public void LoadColumns()
    {
        ddlColumns.DataSource = User.GetItemSearchProperties();
        ddlColumns.DataTextField = "SearchColumn";
        ddlColumns.DataValueField = "CriteriaSearchControlType";
        ddlColumns.DataBind();
        LoadCriteria();
    }

    private void LoadCriteria()
    {
        var controlType = User.GetItemSearchProperties()[ddlColumns.SelectedIndex].CriteriaSearchControlType;

        var ops = User.GetItemSearchProperties()[ddlColumns.SelectedIndex].ValidOperators;
        ddlOperators.DataSource = ops;
        ddlOperators.DataTextField = "key";
        ddlOperators.DataValueField = "value";
        ddlOperators.DataBind();

        switch (controlType)
        {
            case ResourceStrings.ViewFilter_ControlTypes_DDL:
                criteriaDDL.Visible = true;
                criteriaText.Visible = false;

                var crit = User.GetItemSearchProperties()[ddlColumns.SelectedIndex].SearchCriteria;
                ddlCriteria.DataSource = crit;
                ddlCriteria.DataBind();
                break;
            case ResourceStrings.ViewFilter_ControlTypes_Text:
                criteriaDDL.Visible = false;
                criteriaText.Visible = true;
                break;
        }
    }

    public event EventHandler OnColumnChanged;
    public ISearchCriterion FilterOptionsValues { get; set; }
}

}

1 Ответ

1 голос
/ 13 января 2011

Я понял это. Вот мое решение:

Я изменил GetPostBackControl, чтобы искать не только кнопку ссылки, которая вставляет пользовательский элемент управления, но и элементы управления, содержащие идентификатор дочерних элементов управления для вставленного пользовательского элемента управления (чтобы захватить OnSelectedIndexChanged, который запускается изнутри моего пользовательского элемента управления) .

protected Control GetPostBackControl(System.Web.UI.Page page)
    {
        Control control = null;
        string ctrlname = Page.Request.Params["__EVENTTARGET"];
        if (ctrlname != null && ctrlname != String.Empty)
        {
            //if it contains options then it's a control inside my usercontrol
            if (ctrlname.Split('$')[2].Contains("options"))
            {
                var c = new Control();
                c.ID = ctrlname;
                return c;
            }
            else
            {
                control = FindControlRecursive(page, ctrlname.Split('$')[2]);
            }
        }
        else
        {
            string ctrlStr = String.Empty;
            Control c = null;
            foreach (string ctl in Page.Request.Form)
            {
                if (ctl.EndsWith(".x") || ctl.EndsWith(".y"))
                {
                    ctrlStr = ctl.Substring(0, ctl.Length - 2);
                    c = page.FindControl(ctrlStr);
                }
                else
                {
                    c = page.FindControl(ctl);
                }
                if (c is System.Web.UI.WebControls.CheckBox ||
                c is System.Web.UI.WebControls.CheckBoxList)
                {
                    control = c;
                    break;
                }
            }
        }
        return control;
    }

Затем я изменяю событие OnPreInit для поиска элементов управления с идентификатором кнопки ссылки или идентификатором, который содержит «опции»:

protected override void OnPreInit(EventArgs e)
    {
        base.OnPreInit(e);
        System.Web.UI.MasterPage m = Master;
        Control control = GetPostBackControl(this);
        if (control != null)
        {
            if ((control.ClientID == (lbAddAndCondtion.ClientID) || createAgain) || control.ID.Contains("options"))
            {
                createAgain = true;
                CreateUserControl(control.ID);
            }
        }
    }

Критическое исправление было в методе CreateUserControl. В моем исходном коде я пытался напрямую загрузить пользовательский элемент управления из моего общего списка, который был сохранен в Session. Я изменил это, чтобы фактически создать новый экземпляр пользовательского элемента управления, назначить этому новому экземпляру идентификатор, совпадающий с тем, который хранится в Session, а затем добавить его в заполнитель:

protected void CreateUserControl(string controlID)
    {
        try
        {
            if (createAgain && phConditions != null)
            {
                if (OptionControls.Count > 0)
                {
                    phConditions.Controls.Clear();
                    foreach (var c in OptionControls)
                    {
                        FilterOptionsCollectionView foc = new FilterOptionsCollectionView();
                        foc = Page.LoadControl("~/Views/FilterOptionsCollectionView.ascx") as FilterOptionsCollectionView;
                        foc.ID = c.ID;
                        phConditions.Controls.Add(foc);
                    }
                }
            }
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }

Единственное, что я изменил в пользовательском элементе управления, это переместил метод, который загружает мои выпадающие списки, и связал событие OnSelectedIndexChanged с событием OnInit. Теперь я могу динамически загружать столько экземпляров пользовательского элемента управления, сколько мне нужно, и все события внутри пользовательского элемента управления корректно запускаются, и состояние сохраняется во всех обратных передачах !!

Надеюсь, это поможет кому-то еще !!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...