Treeview Casting Confusion?

Nov 6, 2012 at 10:51 PM

I have a treeview that I'm populating with nested sections from a plan object we have.  It's working fine.   Then, I wanted to have the "root" topmost "folder" to display differently than the other folders (with no buttons beside it).  So, my idea was to create another class for the root and use a different template for it.  I can't for the life of me get this to work.  I always get casting errors like now, 

Unable to cast object of type 'Mtap.Mvc.Common.Models.PlanSectionLeaf' to type 'Mtap.Mvc.Common.Models.PlanSectionFolder'.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.InvalidCastException: Unable to cast object of type 'Mtap.Mvc.Common.Models.PlanSectionLeaf' to type 'Mtap.Mvc.Common.Models.PlanSectionFolder'.

Source Error:

Line 276:                                @if (Model.PlanSections != null)
Line 277:                                {
Line 278:                                    @Html.TreeViewFor(
Line 279:                                                m => m.Plan.PlanSectionElements,
Line 280:                                                i => i == 1 ? null : "Children",

 

 

My hierarchy model is correctly filled, I've debugged it.  Here are my model classes,

    // Treeview classes
    public class PlanSectionElement : ISafeCreation
    {
        public PlanSectionElement(string value, string name)
        {
            Value = value;
            Name = name;
        }
        
        public string Value { get; set; }
        public string Name { get; set; }
        public string Parent { get; set; }
        public string Predecessor { get; set; }
        public string Plan { get; set; }
    }

    public class PlanSectionLeaf : PlanSectionElement
    {
        public PlanSectionLeaf(string value, string name)
            : base(value, name)
        {
        }
    }

    public class PlanSectionRoot : PlanSectionElement
    {
        public PlanSectionRoot(string value, string name)
            : base(value, name)
        {
            Children = new List<PlanSectionElement>();
        }

        public List<PlanSectionElement> Children { get; set; }
    }

    public class PlanSectionFolder : PlanSectionElement
    {
        public PlanSectionFolder(string value, string name)
            : base(value, name)
        {
            Children = new List<PlanSectionElement>();
        }

        public List<PlanSectionElement> Children { get; set; }
    }

So, the topmost node is of type PlanSectionRoot, and his children are either PlanSectionFolders or PlanSectionLeafs.

And here is my treeview call,

                                    @Html.TreeViewFor(
                                                m => m.Plan.PlanSectionElements,
                                                i => i == 1 ? null : "Children",
                                                ExternalContainerType.span,
                                                null,
                                                new object[] 
                                                {
                                                    _S.L<Mtap.Mvc.Common.Models.PlanSectionRoot>
                                                    (h => "<span class='folder'>" +h.DisplayFor(m => m.Name).ToString()+"</span>"
                                                    ),

                                                    _S.L<Mtap.Mvc.Common.Models.PlanSectionFolder>
                                                    (h => string.Format("<span>{0} {1} {2} {3}</span>",
                                                        @Html.ActionLink(h.ViewData.Model.Name, "SectionUpdate", "Plan", new { selectedPlanSectionRefId = h.ViewData.Model.Value.ToString() }, null).ToString(),
                                                        @Html.ActionLink("Insert Child", "SectionCreateWizard", "Plan", new { planRefId = h.ViewData.Model.Plan, parentPlanSectionRefId = h.ViewData.Model.Value, predecessorPlanSectionRefId = Guid.Empty }, null).ToString(),
                                                        @Html.ActionLink("Insert Above", "SectionCreateWizard", "Plan", new { planRefId = h.ViewData.Model.Plan, parentPlanSectionRefId = h.ViewData.Model.Parent, predecessorPlanSectionRefId = h.ViewData.Model.Predecessor }, null).ToString(),                
                                                        @Html.ActionLink("Insert Below", "SectionCreateWizard", "Plan", new { planRefId = h.ViewData.Model.Plan, parentPlanSectionRefId = h.ViewData.Model.Parent, predecessorPlanSectionRefId = h.ViewData.Model.Value }, null).ToString())                
                                                    ),
                            
                                                    _S.L<Mtap.Mvc.Common.Models.PlanSectionLeaf>
                                                    (h => string.Format("<span>{0} {1} {2} {3}</span>",
                                                        @Html.ActionLink(h.ViewData.Model.Name, "SectionUpdate", "Plan", new { selectedPlanSectionRefId = h.ViewData.Model.Value.ToString() }, null).ToString(),
                                                        @Html.ActionLink("Insert Child", "SectionCreateWizard", "Plan", new { planRefId = h.ViewData.Model.Plan, parentPlanSectionRefId = h.ViewData.Model.Value, predecessorPlanSectionRefId = Guid.Empty }, null).ToString(),
                                                        @Html.ActionLink("Insert Above", "SectionCreateWizard", "Plan", new { planRefId = h.ViewData.Model.Plan, parentPlanSectionRefId = h.ViewData.Model.Parent, predecessorPlanSectionRefId = h.ViewData.Model.Predecessor }, null).ToString(),                
                                                        @Html.ActionLink("Insert Below", "SectionCreateWizard", "Plan", new { planRefId = h.ViewData.Model.Plan, parentPlanSectionRefId = h.ViewData.Model.Parent, predecessorPlanSectionRefId = h.ViewData.Model.Value }, null).ToString())                
                                                    )
                                                },
                                                (x, y) => x is Mtap.Mvc.Common.Models.PlanSectionLeaf ? 1 : 0,
                                                null,
                                                null,
                                                (x, y) => x is Mtap.Mvc.Common.Models.PlanSectionLeaf ? 1 : 0,
                                                TreeViewMode.InitializeDisplay,
                                                (x) => "allnodes",
                                                (x, y) => TreeViewItemStatus.initializeShow)                              
                                }

if I take out the PlanSectionRoot template and just use Folders and Leafs, everything works fine.  Anybody see anything that stands out?

Thanks so much!

Russell

 

 

 

	

 

 

 

 

 

 

 

 

 

 

 

Coordinator
Nov 7, 2012 at 3:29 AM

For sure the function that chooses the template is wrong!:

(x, y) => x is Mtap.Mvc.Common.Models.PlanSectionLeaf ? 1 : 0

if the class is PlanSectionLeaf the template chosen is the one with index 1 ...THE WRONG ONE template with index 1 is the folder template. Otherwise you choose template 0 that is the root template....so the folder template is never selected. You must add a consition mor into this function (and also in the edit templates one). This way you can test all three classes and select templates 0 1 or 2 accordingly, instead of just templates 0 and 1.

Nov 8, 2012 at 1:22 AM

You my friend are a lifesaver!  :)  I must have just been staring at it too long.  I noticed that when I rearranged the templates that the error I got was different, but just didn't notice the selectors.  Thank you so much!

 

Russell