The content you're reading is getting on in years
This post is on the older side and its content may be out of date.
Be sure to visit our blogs homepage for our latest news, updates and information.
[This post is part of the developer's manual preview published on this blog. You can find temporary TOC here.]
All this has changed in Sitefinity 3.6.
The key idea of the improvements in the new architecture is to allow certain amount of functionality to be easily reused, while at the same time making modifications to the base implementation equally simple. While, reuse was not a problem even in the prior versions, things did get more complex when functionality or presentation needed to be changed.
With the new concept of the Views, developers are now able to cherry pick the Views (single contained unit of functionality) which they wish to reuse completely, reuse partially or implement from scratch, while leaving the rest of module intact.
Let us examine the architectural overview of the Products module, with special focus on the Views and their reuse.
As the legend suggests, we have been able to modify different Views to different degrees depending on our requirements.
First, we have ProductsControlPanel and ProductsView Views which have been completely implemented from the scratch, since we had no use of inheriting from base implementation.
Then, we have different products Views in yellow color which we have modified mostly to add new meta fields that Products module will use and change the labels on the user interface (e.g. where in Generic Content it would say: “Save this item”, we changed to “Save this product”).
Next are the three Views in the gray color on which we only changed the assembly info for embedded templates and localization, since we wanted to use the templates and localization resources from Telerik.Samples.Products assembly as opposed to Telerik.Cms.Engine assembly (where Generic Content module is located). The reason we have done this is to change several labels.
Finally, we have the Views for Comments administration in bluish color. We have not modified anything on these Views and we are using them directly from the Generic Content module. Since we are adding Views by specifying its type (or alternatively virtual path if we are working with user control based views), there is nothing preventing us to add a view which resides in different assembly - provided that we have referenced the view and that its entire implementation matches our requirements.
One of such Views in Products module is the ProductsView View. Since ProductsView is only a container View (does not have its own graphical user interface, but rather displays the first view in the collection of its child views), the code for it is rather simple:
using Telerik.Cms.Engine; |
using Telerik.Cms.Web.UI; |
using Telerik.Cms.Engine.WebControls.Admin; |
using Telerik.Samples.Products.WebControls.Admin.Products; |
using Telerik.Samples.Products.Resources; |
namespace Telerik.Samples.Products.WebControls.Admin |
{ |
/// <summary> |
/// Container view for all product related views |
/// </summary> |
public class ProductsView : ViewModeControl<ProductsControlPanel>, IGenericContentHost |
{ |
/// <summary> |
/// Content Manager used by the control |
/// </summary> |
public ContentManager Manager |
{ |
get |
{ |
return this.Host.Manager; |
} |
} |
/// <summary> |
/// Gets the products manager. |
/// </summary> |
/// <value>The products manager.</value> |
public ProductsManager ProductsManager |
{ |
get |
{ |
return this.Host.ProductsManager; |
} |
} |
/// <summary> |
/// Loads configured views. |
/// </summary> |
protected override void CreateViews() |
{ |
AddView<ProductsItemListView>("ProductsItemListView", "ProductsItemListView_Title", "ProductsItemListView_Description", null, Messages.ResourceManager); |
AddView<ProductEditView>("ProductEditView", "ProductEditView_Title", "ProductEditView_Description", null, Messages.ResourceManager); |
AddView<ProductHistoryView>("ProductHistoryView", "ProductHistoryView_Title", "ProductHistoryView_Description", null, Messages.ResourceManager); |
AddView<ProductNewView>("ProductNewView", "ProductNewView_Title", "ProductNewView_Description", null, Messages.ResourceManager); |
AddView<ProductPreviewView>("ProductPreviewView", "ProductPreviewView_Title", "ProductPreviewView_Description", null, Messages.ResourceManager); |
} |
} |
} |
public class ProductHistoryView : ContentItemHistory<ProductsView> |
After we have declared the View, we will define a new embedded template for the View in which we will be able to change our user interface as needed. To do that we are overriding LayoutTemplateName and LayoutTemplatePath properties like follows:
/// <summary> |
/// Gets or sets the path to a custom layout template for the control. |
/// </summary> |
/// <value></value> |
[WebSysTemplate(ProductHistoryView.layoutTemplateName, "ProductHistoryView_Template_Desc", "/Products", false, "2009-04-10")] |
public override string LayoutTemplatePath |
{ |
get |
{ |
return base.LayoutTemplatePath; |
} |
set |
{ |
base.LayoutTemplatePath = value; |
} |
} |
/// <summary> |
/// Gets the name of the embedded layout template. |
/// </summary> |
/// <value></value> |
protected override string LayoutTemplateName |
{ |
get |
{ |
return ProductHistoryView.layoutTemplateName; |
} |
} |
private const string layoutTemplateName = |
"Telerik.Samples.Products.Resources.ControlTemplates.Backend.ProductHistoryView.ascx"; |
On the other hand, by overriding LayoutTemplateName, we are specifying the name of the embedded template which we wish to use with this View.
Now, that user interface has been modified, we are left with modifications of some functionality. Since Generic Content module in Sitefinity 3.6 has been designed for extensibility, certain virtual methods have been exposed for the purpose of simple View reuse. Following code demonstrates some of them exposed on ContentItemHistory base View:
/// <summary> |
/// Gets the edit command. |
/// </summary> |
/// <param name="itemId">The item id.</param> |
/// <returns></returns> |
protected override string GetEditCommand(Guid itemId) |
{ |
return CreateHostViewCommand<ProductEditView>(itemId.ToString()); |
} |
/// <summary> |
/// Gets the list command. |
/// </summary> |
/// <returns></returns> |
protected override string GetListCommand() |
{ |
return CreateHostViewCommand<ProductsItemListView>(); |
} |
/// <summary> |
/// Gets the preview command. |
/// </summary> |
/// <param name="itemId">The item id.</param> |
/// <returns></returns> |
protected override string GetPreviewCommand(Guid itemId) |
{ |
return CreateHostViewCommand<ProductPreviewView>(itemId.ToString()); |
} |
The important thing to understand about those two properties is that they will default to the assembly in which View is located if not set differently. Now, let us see how in ProductsCategoriesView (View which belongs to Telerik.Samples.Products assembly) we have managed to use the templates and localization already defined in Telerik.Cms.Engine (since we didn’t need to make any changes):
/// <summary> |
/// Gets the type from the assembly containing the embedded resources. |
/// Cannot be null reference. |
/// </summary> |
/// <value></value> |
public override Type AssemblyInfo |
{ |
get |
{ |
return typeof(GenericControlPanel); |
} |
set |
{ |
base.AssemblyInfo = value; |
} |
} |
/// <summary> |
/// Gets the type from the assembly containing the embedded localization resource. |
/// Override if embedded templates are using ASP.NET localization. |
/// </summary> |
/// <value></value> |
public override Type LocalizationAssemblyInfo |
{ |
get |
{ |
return typeof(GenericControlPanel); |
} |
set |
{ |
base.LocalizationAssemblyInfo = value; |
} |
} |
The sample products module discussed in this article can be downloaded from here.
View all posts from The Progress Team on the Progress blog. Connect with us about all things application development and deployment, data integration and digital business.
Let our experts teach you how to use Sitefinity's best-in-class features to deliver compelling digital experiences.
Learn MoreSubscribe to get all the news, info and tutorials you need to build better business apps and sites
Progress collects the Personal Information set out in our Privacy Policy and the Supplemental Privacy notice for residents of California and other US States and uses it for the purposes stated in that policy.
You can also ask us not to share your Personal Information to third parties here: Do Not Sell or Share My Info
We see that you have already chosen to receive marketing materials from us. If you wish to change this at any time you may do so by clicking here.
Thank you for your continued interest in Progress. Based on either your previous activity on our websites or our ongoing relationship, we will keep you updated on our products, solutions, services, company news and events. If you decide that you want to be removed from our mailing lists at any time, you can change your contact preferences by clicking here.