Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Demonstration usage of MultiSelectTreeView.Mvc

0.00/5 (No votes)
7 Sep 2015 1  
This article demonstrates the use of MultiSelectTreeView.Mvc NuGet package in MVC application

Introduction

This article demonstrates the use of MultiSelectTreeView.Mvc NuGet package in MVC application.

Overview of MultiselectTreeView.Mvc package

https://www.nuget.org/packages/MultiSelectTreeView.Mvc/

This package provides a TreeView control facilitating following key features:
- Many-to-many relational data (with obvious support of one-to-one, one-to-many and many-to-one relational data)
- Selection of multiple TreeView nodes
- No limit on number of levels in TreeView
- Submit/ Post data from TreeView control to the specified submit action (HttpPost) of a controller.
- Styling is defaulted to bootstrap, so if the MVC application already has bootstrap then the control will display automatically as per boostrap's styling. Or else, the control is also providing full control over styling.
- Easy to integrate

Demonstation Project can be found at following location - 

https://treeviewmvcdemo.codeplex.com/SourceControl/latest

Demo screen with default styling

Multi level treeview control

How to integrate MultiSelectTreeView.Mvc in your ASP.NET MVC application

Step-1 Install MultiSelectTreeView.Mvc package

- Install MultiSelectTreeView.Mvc package to your ASP.NET MVC application by either using NuGet Package Manager or by executing following command in the Package Manager Console.

Install-Package MultiSelectTreeView.Mvc


This command will install latest version of MultiSelectTreeView.Mvc package to the MVC project. (DLLs, CSS and Javascript files)

This will also check for DTech.Core. If the package is not installed, then it will automatically install the latest version of DTech.Core package.

Step-2 Install AutoMapper package

AutoMapper is used for Object to Object mapping between custom entities into treeview compatible models.
- Install Automapper package (Version 3.3.0 or later) to your ASP.NET MVC application by either using NuGet Package Manager or by executing following command in the Package Manager Console.

Install-Package AutoMapper


Please note this step is recently made manual to support N-Tier architecture where the mapping is not intended to be done in Mvc project. In such cases, you will need to install AutoMapper only in the project where you perform mapping between your custom class to TreeView compatible model.

Step - 3 Install Bootstrap package (Optional)

Bootstrap is by default a styling framework from MVC 5 onwards. The MultiSelectTreeView.Mvc package uses Bootstrap styling by default. If bootstrap is not installed in your MVC project, 

Install-Package bootstrap

Once added, reference the CSS and JS files of bootstrap in MVC views.

Still if you do not wish to use BootStrap, you may have full control over styling of the TreeView control where you can manually style as you like.

Step - 4 Initialize and build a source data collection

Source data collection means the collection (List) of entities which should be displayed in the TreeView control. The entities in source data collection should actually represent child and parent relations.

For example - consider following two classes (used in the demo project)

public class ProductCategory
    {
        public int ProductCategoryId { get; set; }

        public string ProductCategoryName { get; set; }

        public string ProductCategoryDescription { get; set; }        
    }

public class ProductCategoryLevel
    {
        public int ProductCategoryLevelId { get; set; }

        public int ProductCategoryId { get; set; }

        public int ParentProductCategoryId { get; set; }

        public ProductCategory ProductCategory { get; set; }

        public ProductCategory ParentProductCategory { get; set; }        
    }

 

Here, ProductCategoryLevel defines parent-child relations between each ProductCategory instance. This can be any similar object in your application. Such as, Employee and Employee reporting levels, etc.

Step - 5 Configure mapping profile for data transformation

- In order to convert source data collection into TreeView compatible data, we need to define mapping between objects. The mapping should be configured during application start 

Make sure to import following namespaces:

using DTech.Models;
using DTech.Core.Builders;

Following how we have configured mapping profile for our demo project -

using AutoMapper;
using DTech.Models;
using TreeViewHelper.Mvc.Demo.Models;
        protected void Application_Start()
        {
            ......
            SetupMappingProfile();
        }

        public static void SetupMappingProfile()
        {
            AutoMapper.Mapper.CreateMap<ProductCategoryLevel, HierarchyNodeRawModel>()
                            .ForMember(dest => dest.NodeId, opt => opt.MapFrom(src => src.ProductCategoryLevelId))
                            .ForMember(dest => dest.EntityId, opt => opt.MapFrom(src => src.ProductCategoryId))
                            .ForMember(dest => dest.ParentEntityId, opt => opt.MapFrom(src => src.ParentProductCategoryId))
                            .ForMember(dest => dest.NodeTitle, opt => opt.MapFrom(src => src.ProductCategory.ProductCategoryName))
                            .ForMember(dest => dest.NodeDescription, opt => opt.MapFrom(src => src.ProductCategory.ProductCategoryDescription));
        }


Namespace DTech.Models is supplied with the Nuget package, and contains models which are compatible with the TreeView control.
Type HierarchyNodeRawModel represents each node on TreeView.
NodeId >> Must be unique across the collection of HierarchyNodeRawModel. This can be same field as EntityId, if the relation is NOT many-to-many, and EntityId is unique across.
EntityId >> ID field representing child entity
ParentEntityId >> ID field representing parent entity
NodeTitle >> Ideally, a field to display the name of child entity on tree node
NodeDescription >> A field to display description about the child entity on tree node. This is optional, and can be set to blank, if your source collection doesn't have such field.


Step - 6 Build source data collection, and invoke View.

- Instantiate HierarchicalDataBuilder with the type of your source data collection
- Fetch source data collection from your data source (or service) in your controller 
- Construct a string collection identifying ID (NodeId) to default selection of nodes in TreeView, if any.
- Transform the object into TreeView compatible type (i.e., HierarchicalDataModel)
- Pass the transformed model into the View hosting TreeView control

For simplicity of the demo, we have used following -
        public ActionResult Index()
        {

HierarchicalDataBuilder<ProductCategoryLevel> productCategoryLevelsBuilder = new HierarchicalDataBuilder<ProductCategoryLevel>();

            List<ProductCategoryLevel> categoryLevels = ProductCategoryLevel.GetAll();
            List<String> selectedCategoryLevels = new List<string>();
            selectedCategoryLevels.Add("7");
            selectedCategoryLevels.Add("4");
            HierarchicalDataModel dataModel = productCategoryLevelsBuilder.CreateHierarchicalDataModel(categoryLevels, true, "/ProductCategory/Details/[id]", "[id]", selectedCategoryLevels, "HierarchyNodes");
            return View(dataModel);
        }


Remember, in more real scenario, the retrieval of source data collection, and constructing a String collection of selected NodeIds can be very much different from shown above. That can be from a real data store directly or via service depending upon architecture of your application.

Also, we are directly passing HierarchicalDataModel to the view, whereas in real-world scenario, this object may just be a part of a different model. 

For example, There is a Product class which contains collection of ProductCategoryLevel. And the Product class should be used as a model for the view and NOT the transformed object of List<ProductCategoryLevel>. That means, Product class must have HierarchicalDataModel property in it, and should be assigned to the transformed object of List<ProductCategoryLevel>. 
But for the demo purpose we are directly passing HierarchicalDataModel.

_Also, there are various overloads of CreateHierarchicalDataModel method in HierarchicalDataBuilder class, but for demo purpose we are using the one which provides maximum of functionality.
Each overload of this method is documented in the control, and will give you necessary details of the method and each of its parameters in the intellisense._

Some key notes about the method and its parameters, we have used in our demo - 

HierarchicalDataModel dataModel = productCategoryLevelsBuilder.CreateHierarchicalDataModel(categoryLevels, true, "/ProductCategory/Details/[id]", "[id]", selectedCategoryLevels, "HierarchyNodes");


"/ProductCategory/Details/[id]" >> Parameter: ManageActionUrl - URL of the controller action which should be called when user clicks on "Manage" link. [id] is the ID placeholder, and will be replaced by the actual ID value of the node for which the button is displayed.
Please note, Manage link is not appearing always depending upon the overload which is used. And also, "Manage" can be renamed to "View", "Details", or anything you may want by supplying appropriate parameter in the method. 

"[id]" >> Placeholder which should be similar to the ID placeholder specified in "ManageActionUrl"

"HierarchyNodes" >> Parameter: dataBindControlIDPrefix - In MVC when we bind a control array to a view, the Post action expects "name" property in a specific format to enable submitting of model. This should be as same as the ModelName.ControllArrayName. 
For example, if your model bound to the view is Product, then this property should be supplied as "Product.HierarchyNodes", then only you will be able to get selected nodes in Post action.

Step - 7 Design your View

Make sure to import following namespaces

@using DTech.Models;
@using DTech.MVC;


Bind your view with the expected Model

@model DTech.Models.HierarchicalDataModel


_In more real scenario, this can be your Model containing source data collection and HierarchicalDataModel as its properties. For example, Product entity will have List<ProductCategoryLevel> as its property, and hence, HierarchicalDataModel should also be its property.

@Html.Raw(new _TreeViewHelper().GetTreeView(Model))


The above statement will render the data in a tree-view representation on the view.

In case, if the selection needs to be posted to a controller action, then it can be something like -

@using (Html.BeginForm())
{   
    @Html.Raw(new _TreeViewHelper().LoadTreeView(Model))
    <input type="submit" value="Save and Continue" title="Save the selection, and continue to next screen to check the selected Items" />
} 


Step - 8 Handle selection during Submit event

When user clicks a submit button on hosting view, an HttpPost controller action will be called with the submitted model. At this stage, the HierarchicalDataModel must be having selection and non-selection state for each tree node. Use GetSelectedNodeIDs method of the HierarchicalDataBuilder class to retrieve IDs of selected nodes.

For example, 

        [HttpPost]
        public ActionResult Index(HierarchicalDataModel dataModel)
        {
            List<string> selectedProductCategoryLevelIDs = productCategoryLevelsBuilder.GetSelectedNodeIDs(dataModel.HierarchyNodes);
.......
        }


Once the GetSelectedNodeIDs method is called, the String collection should contain IDs of selected nodes. This IDs will identify each selected node, and can be used further to save the selection in database or any other action as per your requirements.

Questions/ Discussions

This document explains an overview and usage of MultiSelectTreeView.Mvc package in MVC application. Feel free to drop a question, or initiate a discussion in case of any information you may require about the package.

Hope you liked this article and demonstration!

History

Version - 2: Installation of Automapper package is now included in the MultiSelectTreeView.Mvc package, so the step suggesting manual installing of AutoMapper is now done away with.

Version - 1: Initial version 

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here