Working with Umbraco Checkboxlist prevalues

Recently, a fellow ASP.NET/Umbraco developer asked me about my approach to working with prevalues of the Checkboxlist datatype in Umbraco from a UserControl.

For a regular CRU(D, the prevalues are deleted when the document containing the datatype is deleted) there’s three steps:

  1. Creating a new document with selected prevalues
  2. Reading prevalues from a documents datatype
  3. Updating the prevalues

I’d like to start with reading the prevalues. What we need is a regular CheckBoxList ASP.NET control in our UserControl:

This will be used to populate the prevalues from a document. To populate/read the prevalues of a document, we can make use of the GetPreValues(int) method from the Umbraco library. This method returns an XPathNodeIterator since the prevalues are stored as XML. When iterating through the prevalues, we can then add a new ListItem with the id and the value of the prevalue to a ListItemCollection which we can use for databinding, like this:

The id ’1100′ used in the umbraco.library.GetPreValues(1100) call is the id of your checkboxlist datatype, which you can find by hovering the datatype in the developer section -> datatypes in Umbraco.

This should leave you with a databound CheckBoxList control corresponding to the Checkboxlist in Umbraco.

For creating a new document where the user have checked some of the ListItems, we need to loop through the ListItems in the ListItemCollection and check if each of them is checked:

For saving a clean string with no extra commas, we simply get the substring starting from position 0 until we hit the last comma.

Last, for Updating the values, we have to compare the CheckBoxList ASP.NET control with the Checkboxlist datatype on the document in Umbraco and add or remove values to/from the comma seperated string:

That’s about it! As always, if you know of a better way of doing this from an ASP.NET UserControl, please let me know :-)

This entry was posted in ASP.NET, Umbraco CMS and tagged , , . Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.

19 Comments

  1. Paul Griffiths
    Posted February 12, 2014 at 2:17 pm | Permalink

    Hi Bo,

    Ive stumbled upon your article whilst looking for a solution to help me. I currently have a user control that uses a checkbox list that i want to allow users to be able to select options and when they submit the form via a button click i want to be able to update the relevant node (which uses a checkbox list datatype) with the corresponding values that have been passed through via the usercontrol. I need this to happen the other way too when the form loads the values taken from node are passed to the user control. Is that what the code above is doing?

    Hopefully you can help me

    Thanks

    Paul

    • Posted February 13, 2014 at 4:40 pm | Permalink

      Hi Paul,

      Yes, that’s basically what this article is about :-) However, I think there might be an easier way to handle prevalues than this. Check this one:

      our.umbraco.org topic

  2. Roger Hughes
    Posted February 13, 2014 at 2:36 pm | Permalink

    Hi, thanks for the example. I’m having an issue however. I only want the user to be able to update the node from the current page. I tried to use the example here to populate the checkbox list but I have an error loading usercontrol:

    //populate the checkbox list
    Document doc = new Document(1050);//ID of the document type
    XPathNodeIterator preValueRootElementIterator = umbraco.library.GetPreValues(1091); //ID of the property type
    preValueRootElementIterator.MoveNext();
    XPathNodeIterator preValueIterator =
    preValueRootElementIterator.Current.SelectChildren(“functionType”, “”);

    //Add prevalues as a new ListItem to a ListItemCollection
    ListItemCollection preValueList = new ListItemCollection();
    while (preValueIterator.MoveNext())
    {
    preValueList.Add(new ListItem(preValueIterator.Current.Value,
    preValueIterator.Current.GetAttribute(“id”, “”)));
    }

    //Bind preValues to the checkbox list
    cbFunctionTypes.DataSource = preValueList;
    cbFunctionTypes.DataTextField = “Text”;
    cbFunctionTypes.DataBind();

    //Set the checked prevalues
    if (!doc.getProperty(“class”).Value.ToString().Equals(string.Empty)
    && doc.getProperty(“class”).Value != null)
    {
    foreach (ListItem item in cbFunctionTypes.Items)
    {
    if (doc.getProperty(“class”).Value.ToString().Split(‘,’).Contains(item.Value))
    {
    item.Selected = true;
    }
    }
    }

  3. Roger Hughes
    Posted February 13, 2014 at 3:07 pm | Permalink

    Hi, i think we almost have it working. We’re a bit confused as to where you get “klasse” from on:
    //Set the checked prevalues
    if (!doc.getProperty(“klasse”).Value.ToString().Equals(string.Empty)
    && doc.getProperty(“klasse”).Value != null)
    {
    foreach (ListItem item in cbFunctionTypes.Items)
    {
    if (doc.getProperty(“klasse”).Value.ToString().Split(‘,’).Contains(item.Value))
    {
    item.Selected = true;
    }
    }
    }

    Our property in the document is called functionType. We are using a standard checkbox list umbraco data type so only have text and value there. Could you explain please? Thanks

  4. Roger Hughes
    Posted February 13, 2014 at 3:14 pm | Permalink

    Do we assume “klasse” is the alias of the document type property?

  5. Roger Hughes
    Posted February 13, 2014 at 3:57 pm | Permalink

    Hi again,
    its almost working perfectly now apart from the list items not being selected. I have added a literal that populates correctly with the comma separated values but the checkboxes render unchecked. Any help would be greatly appreciated:

    //Set the checked prevalues
    if (!doc.getProperty(“functionType”).Value.ToString().Equals(string.Empty)
    && doc.getProperty(“functionType”).Value != null)
    {
    foreach (ListItem item in cbFunctionTypes.Items)
    {
    if (doc.getProperty(“functionType”).Value.ToString().Split(‘,’).Contains(item.Value))
    {
    item.Selected = true;
    }
    }
    litTest.Text = (doc.getProperty(“functionType”).Value.ToString();
    }

  6. Posted February 13, 2014 at 4:33 pm | Permalink

    Hi Roger,

    Thanks for your interest in this (rather old ;-) ) article.

    Yes, “klasse” if the alias of my document type.

    Have you tried to see if there are any list items in the cbFunctionTypes.Items collection? :-)

  7. Roger Hughes
    Posted February 13, 2014 at 4:39 pm | Permalink

    Hi, thanks for getting back to me. Yeah, there are 3 checkbox items. 2 are selected from umbraco with id’s 13,15 (14 being unchecked)
    In the backend they are selected.
    The control renders the checkbox list and I have added a literal to test the response outside of the if (doc.getProperty(“functionType”).Value.ToString().Split(‘,’).Contains(item.Value)) :

    litTest.Text = (doc.getProperty(“functionType”).Value.ToString();

    The literal populates with 13,15 as per the selected values in umbraco.
    Im just struggling with setting the checkbox values

    Thanks

    Roger

    • Posted February 13, 2014 at 4:46 pm | Permalink

      Hi Roger,

      Alright, so what happens if we just loop through the Umbraco checkboxlist values without any conditions? Like this:


      foreach(var item in cbFunctionTypes.Items)
      {
      item.Selected = doc.getProperty("functionType").Value.ToString().Contains(item.Value);
      }

      Removing the first if condition:

      if (!doc.getProperty(“functionType”).Value.ToString().Equals(string.Empty)
      && doc.getProperty(“functionType”).Value != null)

      Does it populate all three options then? :-)

      • Paul Griffiths
        Posted February 13, 2014 at 7:58 pm | Permalink

        Hi Bo, No sooner did i get over one hurdle to be stopped by another lol. Again using your code I am trying to populate the checklist located in umbraco from the user control when the update button is selected. Can you inspect my code to see where I could be going wrong please.

        protected void update_Click(object sender, EventArgs e)
        {
        if (Page.IsValid)
        {

        // Get the Document object via the nodefactory
        Document currentPage = new Document(Node.GetCurrent().Id);

        // Update the name of the page (text property)
        currentPage.Text = pageName.Text;

        // Update the bodyText property
        currentPage.getProperty(“bodyText”).Value = bodyText.Text;

        // Update the checkbox values

        // start by getting the old prevalues from umbraco
        Document doc = new Document(currentPage.Id);//ID of the document type

        //Document doc = new Document(currentPage.Id);//ID of the document type
        string classValues = doc.getProperty(“functionType”).Value.ToString();

        //loop through the list item collection in the user control
        foreach (ListItem item in cbFunctionTypes.Items)
        {
        if (item.Selected)
        {
        //If the current item is selected
        //and it is not in the old prevalues list in umbraco
        //add it to the prevalue string
        if (!classValues.Contains(item.Value))
        classValues += “,” + item.Value;
        }
        else
        {
        //if the current item is not selected an
        //already exists in the old prevalues list in umbraco
        //it needs to be removed
        if (classValues.Contains(item.Value))
        {
        string result = “”;

        //Check if the value is in the first (10,11,12)
        // in the old prevalues
        if (classValues.Contains(item.Value + “,”))
        {
        result = classValues.Replace(item.Value + “,”, string.Empty);
        }
        //check if the value is in-between or last
        else if (classValues.Contains(“,” + item.Value))
        {
        result = classValues.Replace(“,” + item.Value, string.Empty);
        }
        // check if theres just one prevalue stored
        else
        {
        result = classValues.Replace(item.Value, string.Empty);
        }

        classValues = result;
        }
        }
        }
        //save the new prevalue string
        doc.getProperty(“functionType”).Value = classValues;

        // Publish
        currentPage.Publish(currentPage.User);

        // Refresh runtime cache
        umbraco.library.PublishSingleNode(currentPage.Id);
        }
        }
        }

        Cheers mate

        • Posted February 13, 2014 at 8:18 pm | Permalink

          Hiya Paul,

          What exactly is the error? Doesn’t the checkbox values get saved, or? :-)

          • Paul Griffiths
            Posted February 13, 2014 at 8:26 pm | Permalink

            Hi Bo,

            If I check the boxes from the website and press save when the page reloads the values which I have selected stay selected which is good but when i go into the umbraco back office the values that are selected on the front end dont get carried through to the back end checklist and vice versa.

            Hope that makes sense mate.

          • Posted February 13, 2014 at 8:32 pm | Permalink

            Hi Paul,

            I think it may be because you’re setting the functionType property in the “doc” document, but you’re publishing the “currentPage” document :-) the “doc” document is never saved/published then.

  8. Roger Hughes
    Posted February 13, 2014 at 5:09 pm | Permalink

    That broke the control… If I comment out the initial if statement here:

    //Set the checked prevalues
    //if (!doc.getProperty(“functionType”).Value.ToString().Equals(string.Empty)
    // && doc.getProperty(“functionType”).Value != null)
    //{
    foreach (ListItem item in cbFunctionTypes.Items)
    {
    if (doc.getProperty(“functionType”).Value.ToString().Split(‘,’).Contains(item.Value))
    {
    item.Selected = true;
    }
    }
    // litTest.Text = (doc.getProperty(“functionType”).Value.ToString();
    //}

    Nothing populates again. But if I remove this statement:
    if (doc.getProperty(“functionType”).Value.ToString().Split(‘,’).Contains(item.Value))

    They all populate as you would expect

  9. Roger Hughes
    Posted February 13, 2014 at 5:36 pm | Permalink

    Hi Bo, I think i know what the issue is, i just dont know how to resolve it…

    The values of the checkboxes are not numeric, they are being populated with the actual text values.

    However, doc.getProperty(“functionType”).Value.ToString(); returns the id’s

    Any ideas?

    Here’s the html output example:

  10. Roger Hughes
    Posted February 13, 2014 at 5:37 pm | Permalink

    input type=”checkbox” value=”Weddings” name=”ctl00$ctl00$ctl00$ContentPlaceHolderDefault$cp_content$UpdateVenue_2$cbFunctionTypes$0″ id=”ContentPlaceHolderDefault_cp_content_UpdateVenue_2_cbFunctionTypes_0″

  11. Roger Hughes
    Posted February 13, 2014 at 5:44 pm | Permalink

    Hi Bo,
    I’ve managed to solve the issue…

    I needed to add – cbFunctionTypes.DataValueField = “Value”;

    Thanks for the help anyway! :)

    • Posted February 13, 2014 at 5:53 pm | Permalink

      Hi Roger,

      Perfect! :-) Hope it works as it should. However, I’d like to point out that this post is quite old and we can now make use of the umbraco.cms.businesslogic.datatype; namespace now to get hold of the prevalues. Check this post if it catches your interest: our.umbraco.org post

  12. Paul Griffiths
    Posted February 14, 2014 at 9:07 am | Permalink

    Hey Bo,

    Just like to update you. I managed to solve the issue I was getting by using the information that you supplied. Now my code looks like below and I am able to add an option to the datatype in the umbraco back office and it will update on all properties that use it and will display on the user control. Also if the user checks an option from the front end via the user control or if its done via the backend through the content tree node it updates simultaniously :) Happy days.

    if (Page.IsValid)
    {

    // Get the Document object via the nodefactory
    Document currentPage = new Document(Node.GetCurrent().Id);

    // Update the name of the page (text property)
    currentPage.Text = pageName.Text;

    // Update the bodyText property
    currentPage.getProperty(“bodyText”).Value = bodyText.Text;

    // Update the checkbox values
    //Document doc = new Document(currentPage.Id);//ID of the document type
    string classValues = currentPage.getProperty(“functionType”).Value.ToString();
    foreach (ListItem item in cbFunctionTypes.Items)
    {
    if (item.Selected)
    {
    if (!classValues.Contains(item.Value))
    classValues += “,” + item.Value;
    }
    else
    {
    if (classValues.Contains(item.Value))
    {
    string result = “”;

    if (classValues.Contains(item.Value + “,”))
    {
    result = classValues.Replace(item.Value + “,”, string.Empty);
    }
    else if (classValues.Contains(“,” + item.Value))
    {
    result = classValues.Replace(“,” + item.Value, string.Empty);
    }
    else
    {
    result = classValues.Replace(item.Value, string.Empty);
    }
    classValues = result;
    }
    }
    }
    currentPage.getProperty(“functionType”).Value = classValues;

    Thanks again for your help mate

    Paul

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>


six - 5 =