Table of Contents

ViewModels

In DynamicWeb we have to different ways of passing information to the frontend

  • TemplateTags
  • ViewModels

In some cases you need to make some information available, which is not part of a standard DynamicWeb. In these cases you need to extend either the TemplateTags or the ViewModels with the extra information.

Extending ViewModels

In DynamicWeb you can extend our existing ViewModels with new properties, if the default information does not cover your needs.

When you need to extend a ViewModel, you first need to identify which ViewModel you want to extend. Here you have a list of all the ViewModels which inherit from ViewModelBase, and here there's a list of the ViewModels inheriting from FillableViewModelBase

When you know which ViewModel you want to extend, you can open your favourite IDE and start implementing.

To start extending an existing ViewModel, you need to create a new class, that inherits from the ViewModel, you want to extend. In the new class, you can override an existing method or property by using the new keyword or add completely new properties and methods, which can return the data you need.

It's not possible to change the original values on the ViewModel, because they will be overwritten as part of the ViewModel instantiation, so if you need to return some different data in a property, you need to create your own property in your class, and have that return the correct data.

using Dynamicweb.Frontend;

namespace ViewModelExtensibility
{
    public class PageInfoViewModelExtended : PageInfoViewModel
    {
        private object _instance;
        public PageInfoViewModelExtended()
        {
            //this is initialisation. The model does not have anyting set at this point.
            //Initialize objects, i.e. services, that can be used throughtout the instance - i.e. to get addtional data.
            _instance = new object();

            //This will not work as the header will be overriden later in the initialisation process of this object.
            base.Name = "Set name in constructor does not work";
        }

        /// <summary>
        /// Take over default property of the base viewmodel. Suitable to change default behavior
        /// </summary>
        public new string Name
        {
            get
            {
                return $"{base.Name} changed1";
            }
        }

        /// <summary>
        /// Addtional data property available in template. Suitable for additional data
        /// </summary>
        public string MetaTitleOrName
        {
            get
            {
                //Retrive the actual page from the database to access information, which is not available on the PageViewModel
                var page = Dynamicweb.Content.Services.Pages.GetPage(base.ID);
                if (!string.IsNullOrEmpty(page.MetaTitle))
                {
                    return page.MetaTitle;
                }
                else
                {
                    return page.GetDisplayName();
                }
            }
        }
    }
}

Item-based ViewModels

In some cases you have ViewModels, which is based on an Item. If you only want to extend a ViewModel working on a specific ItemType, then you can do that by adding the AddInName, with the SystemName of the ItemType, to the class.

using System;
using System.Collections.Generic;
using System.Text;
using Dynamicweb.Frontend;
using Dynamicweb.Rendering;
using Dynamicweb.Extensibility.AddIns;


namespace Dynamicweb.Examples.Rendering
{
    /// <summary>
    /// Custom paragraph viewmodel for specific item type. Use AddInName attribute with the item type name. See <see cref="AddInName"/>
    /// </summary>
    [AddInName("MultiPurposeParagraphInfo")]
    public class SwiftPosterViewModel : ParagraphViewModel
    {
        private object _instance;
        public SwiftPosterViewModel()
        {
            //this is initialisation. The model does not have anyting set at this point.
            //Initialize objects, i.e. services, that can be used throughtout the instance - i.e. to get addtional data.
            _instance = new object();

            //This will not work as the header will be overriden later in the initialisation process of this object. Don't try to initialize any properties of the base class.
            base.Header = "Seting the header inside the constructor does not work";
        }

        /// <summary>
        /// Take over default property of the base viewmodel. Suitable to change default behavior
        /// </summary>
        public new string Header
        {
            get
            {
                return $"{base.Header} changed1";
            }
        }

        /// <summary>
        /// Addtional data property available in template. Suitable for additional data
        /// </summary>
        public string NameOrTile
        {
            get
            {
                if (Item.GetRawValue("Title") is object)
                {
                    return Item.GetRawValue("Title").ToString();
                }
                else
                {
                    return $"From nameOrTitle prop: {Header}";
                }
            }
        }

        /// <summary>
        /// Method to call from template using data from the model instance. Suitable for rendering logic
        /// </summary>
        /// <returns></returns>
        public string GetPosterPadding()
        {
            string posterPadding = Item.GetRawValueString("ContentPadding", string.Empty);
            string posterPaddingClass = "px-3";

            switch (posterPadding)
            {
                case "none":
                    posterPaddingClass = " p-3 px-xl-3 py-xl-4";
                    break;
                case "small":
                    posterPaddingClass = " p-3 p-xl-4";
                    break;
                case "large":
                    posterPaddingClass = " p-4 p-xl-5";
                    break;
            }
            return posterPaddingClass;
        }
    }


    [AddInName("MultiPurposeParagraphInfo")]
    public class SwiftPosterInfoViewModel : ParagraphInfoViewModel
    {
        /// <summary>
        /// Take over default property of the base viewmodel. Suitable to change default behavior
        /// </summary>
        public new string Name
        {
            get
            {
                return $"{base.Name} changed2";
            }
        }

        /// <summary>
        /// Addtional data property available in template. Suitable for additional data
        /// </summary>
        public string NameOrTile
        {
            get
            {
                if (Item.GetRawValue("Title") is object)
                {
                    return Item.GetRawValue("Title").ToString();
                }
                else
                {
                    return $"From nameOrTitle prop: {Name}";
                }
            }
        }

        /// <summary>
        /// Method to call from template using data from the model instance. Suitable for rendering logic
        /// </summary>
        /// <returns></returns>
        public string GetPosterPadding()
        {
            string posterPadding = Item.GetRawValueString("ContentPadding", string.Empty);
            string posterPaddingClass = "px-3";

            switch (posterPadding)
            {
                case "none":
                    posterPaddingClass = " p-3 px-xl-3 py-xl-4";
                    break;
                case "small":
                    posterPaddingClass = " p-3 p-xl-4";
                    break;
                case "large":
                    posterPaddingClass = " p-4 p-xl-5";
                    break;
            }
            return posterPaddingClass;
        }
    }
}
To top