/// <summary>
        /// Returns a table with checkbox options for a model property
        /// </summary>
        /// <param name="htmlHelper">The HTML helper instance that this method extends.</param>
        /// <param name="expression">An expression that contains the property to render</param>
        /// <param name="selectList">A collection of SelectListItem objects that are used to populate the drop-down list</param>
        /// <param name="attributes">Personalized attributes to set on table</param>
        public static MvcHtmlString CheckBoxTableFor <TModel, TProperty>(this HtmlHelper <TModel> htmlHelper, Expression <Func <TModel, TProperty> > expression, IEnumerable <SelectListItem> selectList, AttributesTable attributes)
        {
            var tableBody = new TagBuilder("tbody");

            attributes = CreateTableContent(ref tableBody, selectList, attributes);

            return(MvcHtmlString.Create(CreateBaseTable(tableBody, attributes).ToString(TagRenderMode.Normal)));
        }
 //para criar a estrutura principal da tabela (cria theader e junta tbody):
 private static TagBuilder CreateBaseTable(TagBuilder tableBody, AttributesTable attributes)
 {
     return(CreateBaseTable(tableBody, attributes, null));
 }
        //para criar o conteudo da tabela (tbody):
        private static AttributesTable CreateTableContent(ref TagBuilder tableBody, IEnumerable <SelectListItem> selectList, AttributesTable attributes)
        {
            //criação de selectList com os dados a expor na tabela:
            var newList        = new SelectList(selectList, "Id", (selectList as MultiSelectList).DataTextField);
            var selectedValues = (selectList as SelectList).SelectedValue as ICollection;

            if (selectedValues != null)
            {
                newList = new SelectList(selectedValues, "Id", (selectList as MultiSelectList).DataTextField);
            }

            if (selectList != null)
            {
                int index = 0, countSelected = 0;

                foreach (var item in selectList)
                {
                    try
                    {
                        //verifica se o item conincide com os itens selecionados no model:
                        foreach (var selectedItem in from object selectedItem in selectedValues let valor = selectedItem.getPropertyValue((selectList as MultiSelectList).DataTextField) where selectedItem.getPropertyValue((selectList as MultiSelectList).DataTextField).ToString() == item.Text select selectedItem)
                        {
                            item.Selected = true;
                            if (attributes.isBackoffice)
                            {
                                item.Selected = bool.Parse(selectedItem.getPropertyValue("Selected").ToString().ToLower());
                            }
                            break;
                        }
                    }
                    catch (Exception) {}


                    //criação de nova linha da tabela:
                    var newTR = new TagBuilder("tr");
                    newTR.MergeAttribute("id", index.ToString());
                    newTR.AddCssClass(index % 2 == 0 ? "odd" : "even");


                    //criação de checkbox a apresentar na tabela:
                    var checkbox = new TagBuilder("input");
                    checkbox.MergeAttribute("type", "checkbox");
                    if (attributes.isBackoffice)
                    {
                        checkbox.MergeAttribute("data-fieldname", "Selected");
                    }
                    if (attributes.AllChecked)
                    {
                        checkbox.MergeAttribute("value", "true");
                        checkbox.MergeAttribute("checked", "true");
                    }
                    else
                    {
                        checkbox.MergeAttribute("value", item.Selected.ToString().ToLower());
                        checkbox.MergeAttribute("checked", item.Selected.ToString().ToLower());
                    }


                    //à tabela são também adicionados campos (hidden) referentes ao Id da propriedade e à sua descrição:
                    var hiddenId = new TagBuilder("input");
                    hiddenId.MergeAttribute("type", "hidden");
                    hiddenId.MergeAttribute("value", item.Value);
                    hiddenId.MergeAttribute("id", "isId");
                    hiddenId.MergeAttribute("data-fieldname", String.IsNullOrEmpty(attributes.IdName) ? (selectList as MultiSelectList).DataValueField : attributes.IdName);

                    var hiddenDesc = new TagBuilder("input");
                    hiddenDesc.MergeAttribute("type", "hidden");
                    hiddenDesc.MergeAttribute("value", item.Text);
                    hiddenDesc.MergeAttribute("id", "isName");
                    hiddenDesc.MergeAttribute("data-fieldname", (selectList as MultiSelectList).DataTextField);


                    //atualização dos campos a inserir na tabela, ou seja, caso no model esses valores estejam selecionados, esse facto deve-se verifica visualmente e no momento de submissão dos dados:
                    if (selectedValues != null && selectedValues.Count != 0)
                    {
                        if (newList.Any(selectedItem => (String.IsNullOrEmpty(selectedItem.Text) && selectedItem.Value == item.Value) || (!String.IsNullOrEmpty(selectedItem.Text) && selectedItem.Text == item.Text && item.Selected)))
                        {
                            checkbox.MergeAttribute("value", "true");
                            checkbox.MergeAttribute("checked", "true");

                            if (!String.IsNullOrEmpty(attributes.FieldName))
                            {
                                //para os valores chegarem realmente selecionados ao controller deve-se garantir isso definindo o nome da coleção, o indice do objeto e o nome e valor de cada propriedade:
                                if (attributes.isBackoffice)
                                {
                                    checkbox.MergeAttribute("name", attributes.FieldName + "[" + countSelected + "].Selected"); // para desaparecer no futuro
                                }
                                hiddenId.MergeAttribute("name", attributes.FieldName + "[" + countSelected + "]." + (String.IsNullOrEmpty(attributes.IdName) ? (selectList as MultiSelectList).DataValueField : attributes.IdName));
                                hiddenDesc.MergeAttribute("name", attributes.FieldName + "[" + countSelected + "]." + (selectList as MultiSelectList).DataTextField);
                            }
                            countSelected++;
                        }
                    }

                    //adiciona-se todos os campos aos respetivos TDs, adicionam-se os TDs à nova linha criada, e adiciona-se a linha ao tbody da tabela:
                    newTR.InnerHtml     += "<td>" + hiddenId + hiddenDesc + checkbox + "</td><td>" + item.Text + "</td>";
                    tableBody.InnerHtml += newTR;
                    index++;
                }

                if (index == countSelected && countSelected != 0)
                {
                    attributes.AllChecked = true;
                }
            }

            return(attributes);
        }