1-888-365-2779
+1-888-365-2779
Try Now
More in this section

Forums / Developing with Sitefinity / Control population in ContentView

Control population in ContentView

6 posts, 0 answered
  1. Andree
    Andree avatar
    44 posts
    Registered:
    11 Jan 2010
    08 Feb 2010
    Link to this post
    Hi Ivan,

    I've been struggling through the creation of my custom ContentView and I'm almost there with it now.

    One issue I'm having is that of content population and value selection. In my content view, I have a DropDownList that during the CreateContentList() method, it populates it with all available categories:

    /// <summary>
    /// Populate list container controls
    /// </summary>
    protected override void CreateContentList()
    {
        // base creation
        base.CreateContentList();
        // get categories drop down list
        DropDownList categories = ListContainer.GetControl<DropDownList>("Category", true);
        // get sub-categories
        ContentManager manager = new ContentManager("Articles");
        categories.DataTextField = "CategoryName";
        categories.DataValueField = "CategoryName";
        categories.DataSource = manager.GetCategories();
        categories.DataBind();
    }

    However, when I try to pick up its selected value from the GetFilterBuilder() method, like so:

    protected override ContentFilterBuilder GetFilterBuilder()
    {
        // get filtering controls
        ListControl category = ListContainer.GetControl<ListControl>("Category", true);
        ITextControl keywords = ListContainer.GetControl<ITextControl>("Keywords", true);
        ContentFilterBuilder builder = base.GetFilterBuilder();
        if (!String.IsNullOrEmpty(category.SelectedValue))
        {
            builder.AddFilter(new MetaSearchInfo(MetaValueTypes.ShortText, "Category1", category.SelectedValue, SearchCondition.Equal, JoinType.And));
        }
        return builder;
    }

    The SelectedValue always returns as the first selected item. I'm assuming this is because the control gets rebound every time there's a postback, but without it being bound, the items don't have persistence.

    How should I go about populating a data source of a control within the ContentView so it persists?


    Regards,
    Alvaro

  2. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    16 Jun 2017
    08 Feb 2010
    Link to this post
    Hi Alvaro,

    1. You need to create a control reference to DropDownList control outside of CreateContentList() method.

    2. You could filter the control in CreateChildControls(), before calling the base

    protected override void CreateChildControls()
        {
            var manager = new ContentManager("Articles");
            IList categories= manager.GetCategories();
            DropDownList1.DataSource = categories;
            DropDownList1.AutoPostBack = true;
            DropDownList1.DataBind();
            
            ContentFilterBuilder filterBuilder = new ContentFilterBuilder(this);
            filterBuilder.AddFilter(new ContentFilterStatement("Category", DropDownList1.SelectedItem.Text, ContentFilter.Condition.Equal, ContentFilter.JoinType.And));
        }
     

    Greetings,
    Ivan Dimitrov
    the Telerik team

    Watch a video on how to optimize your support resource searches and check out more tips on the blogs.
    Follow the status of features or bugs in PITS and vote for them to affect their priority.
  3. Andree
    Andree avatar
    44 posts
    Registered:
    11 Jan 2010
    08 Feb 2010
    Link to this post
    Hi Ivan,

    I have created an external reference within the ContentView itself:

    protected ListControl Categories
    {
        get { return ListContainer.GetControl<ListControl>("Category", true); }
    }

    And moved my binding code to the CreateChildControls as recommended:

    protected override void CreateChildControls()
    {
        base.CreateChildControls();
        // get sub-categories
        ContentManager manager = new ContentManager("Articles");
        Categories.DataTextField = "CategoryName";
        Categories.DataValueField = "CategoryName";
        Categories.DataSource = manager.GetCategories();
        Categories.DataBind();
        if (!String.IsNullOrEmpty(Categories.SelectedItem.Value))
        {
            ContentFilterBuilder builder = new ContentFilterBuilder(this);
            builder.AddFilter(new ContentFilterStatement("Category1", Categories.SelectedItem.Value, ContentFilter.Condition.Equal, ContentFilter.JoinType.And));
        }
    }

    However, directly after binding the categories dropdown to all existing categories, the SelectedItem automatically becomes the first one in the list (index 0).

    When the page loads, the value of the drop down, visually, has changed, but in code, the selected value is always the first item, suggesting the order in which the page sets the control values is different to the above mentioned.

    My problem still remains.


    Regards,
    Alvaro
  4. Andree
    Andree avatar
    44 posts
    Registered:
    11 Jan 2010
    08 Feb 2010
    Link to this post
    After a bit of further investigation, I've identified the issue as being the page lifecycle and order of events

    When checking for the SelectedItem's value in the OnLoad method, the value is correctly set, but by that point, adding new filters to the ContentFilterBuilder is too late - the ContentList has already been created. This means the filter does not kick in until the following postback.

    I have tried calling CreateContentList() again from the Load event, after adding the new filter, but there's a "lag" of one postback for the list to be re-created. If I select a category, it auto postbacks and shows the full content list. If I then select another category, after the auto postback, it filters the content from my first chosen category.

    protected override void CreateChildControls()
           {
               base.CreateChildControls();
               // get sub-categories
               ContentManager manager = new ContentManager("Articles");
               Categories.DataTextField = "CategoryName";
               Categories.DataValueField = "CategoryName";
               Categories.DataSource = manager.GetCategories();
               Categories.DataBind();
           }
           protected override void OnLoad(EventArgs e)
           {
               ContentFilterBuilder builder = new ContentFilterBuilder(this);
               builder.ClearFilter();
               if (!String.IsNullOrEmpty(Categories.SelectedItem.Value))
               {
                   builder.AddFilter(new ContentFilterStatement("Category1", String.Format("\"{0}\"", Categories.SelectedItem.Value), ContentFilter.Condition.Equal, ContentFilter.JoinType.And));
                   CreateContentList();
               }
               base.OnLoad(e);
           }

    Keeping in mind that by the time CreateDataSource() and GetFilterBuilder() get called, the dropdownlist hasnt been populated with the correct selected value, is there a better place to add the filtering code, or a way to re-create the content list?

    Regards,
    Alvaro

  5. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    16 Jun 2017
    08 Feb 2010
    Link to this post
    Hello Alvaro,

    1. You execute all logic from CreateChildControls and then apply the filter although you can do it before that.
    2. You need to check whether the page is post back, otherwise you bind the DropDownList/RadComboBox each time which results in the performance.
    3. It is better to create a neutral value for the DropDownList/RadComboBox

    if (!Page.IsPostBack)
            {
                BindCombo();
            }
            FitlerData();
     
    ....
      ....
     
     
    public void FitlerData()
        {
     
            ContentFilterBuilder filter = new ContentFilterBuilder(this);
            //CLEAR THE FILTER FIRST OTHERWISE YOU WILL GET WRONG RESULTS
            filter.ClearFilter();
            // CREATE A DEFAULT VALUE CALLED *UNCATEGORIZED*
           if (RadComboBox1.SelectedItem !=null && RadComboBox1.SelectedItem.Text != "* Uncategorized *")
            {
                filter.AddFilter(new ContentFilterStatement("Category", RadComboBox1.SelectedItem.Tex , ContentFilter.Condition.Equal));
                
            }
        }


    Best wishes,
    Ivan Dimitrov
    the Telerik team

    Watch a video on how to optimize your support resource searches and check out more tips on the blogs.
    Follow the status of features or bugs in PITS and vote for them to affect their priority.
  6. Andree
    Andree avatar
    44 posts
    Registered:
    11 Jan 2010
    08 Feb 2010
    Link to this post
    Hi Ivan,

    I understand what you're saying, but the problem is that the dropdown list isn't populated with all items and selected value by the time CreateChildControls().

    Below is a screenshot of the first time the control is run:

    http://www.haushinka.org/media/sitefinity/screenshot_1.jpg

    There is no postback so the categories drop down is selected. The very first category "All Categories" is a manual entry that is in the .ascx template ("neutral value" as you call it). All other entries come from the manager.GetCategories() method.

    Once the page is loaded, it looks like this:

    http://www.haushinka.org/media/sitefinity/screenshot_2.jpg

    Up to this point there's no problem. The Categories drop down has AutoPostback="true", so for the next postback, I simply clicked on "Marketing" from the Categories drop down. In the next postback, we get the following:

    http://www.haushinka.org/media/sitefinity/screenshot_3.jpg

    Because there has been a postback, the populating code is not called, but at this point in the control's lifecycle, the items from the ViewState have not been re-populated, nor has the SelectedItem. Because of this, all we see is the manual "All categories" entry.

    By the time the page finishes loading, and the markup is outputted, it looks like this:

    http://www.haushinka.org/media/sitefinity/screenshot_4.jpg

    This shows that .NET has re-populated the dropdown with the existing items from the ViewState, and set the selected item to "Marketing" which was my original selection before the page was posted back

    You are telling me to check for the SelectedItem within CreateChildControls, but what I am saying is that ASP.NET's control life cycle hasn't reached the point of restoring the ViewState of the drop down list, so it is not possible to retrieve the value of it at that point.


    Alvaro

Register for webinar
6 posts, 0 answered