Telerik blogs

Hello everyone, and welcome to the second tutorial in my series of tutorials about the Telerik CAB Enabling Kit (TCEK). This week I will be talking about the UIExtensionSites supported in the TCEK. The TCEK comes with a number of UI Adapters that provide support for the following controls.

  • RadMenu
  • RadToolStrip
  • RadPanelBar
  • RadTreeView

These controls are supported through the registration of custom Adapter Factories and Command Adapters. Adapter Factories simplify the task of creating custom UI Adapters for individual controls. Command Adapters allow you to add invokers and/or set command status on specific controls. In the last tutorial, we created a TCEK enabled project, and through having done this, these adapters are now registered for us on program startup.

In this tutorial, we will be focusing on the RadMenu and RadToolStrip. The program we will be creating is a simple “asset management” application that contains a RadMenu, RadToolStrip, and RadGridView as its core components. The RadMenu and RadToolStrip are created in the main ShellLayoutView and are registered as UIExtensionSites. The RadGridView is the main component in the AssetManager module. The AssetManager module registers  RadMenuItems and RadButtonElements with the UIExtensionSites to allow for control and manipulation of the RadGridView through CommandHandlers.

Program Screenshot

Figure 1. The Asset Management Application

I am going to start with the TCEK Enabled project I created in tutorial 1. If you don’t have the source to that project, you may download it here. Also, if you have not yet had a chance to read through the first tutorial, you may do so by going here. Lets get started!

Setting Up the ShellLayoutView

In this series of steps, we will create the ShellLayoutView. This view is the primary view of our application. It will contain the main workspace, RadToolStrip, and RadMenu. The RadToolStrip and RadMenu will be the primary UIExtensionSites used throughout the program.

  1. Open the TCEK Enabled project in Visual Studio.
  2. Expand the Infrastructure.Layout project and double click ShellLayoutView.cs to open it in the designer.
  3. Select and delete all of the controls in the design view except for the DeckWorkspace control named _rightWorkspace.
  4. Place _rightWorkspace in a RadPanel and rename it to _mainWorkspace.
  5. Drag a RadMenu and a RadToolStrip into the designer.
    1. Delete the radToolStripItem1 from the Toolstrip.
  6. Right click ShellLayoutView.cs and select View Code.
    1. Remove the line of code that assigns the left workspace.
    2. Refactor the WorkspaceNames.RightWorkspace constant to be named WorkspaceNames.MainWorkspace.
      public ShellLayoutView() 
          InitializeComponent(); 
          _mainWorkspace.Name = WorkspaceNames.MainWorkspace; 
       
    3. Remove all unnecessary method and properties such as MainStatusStrip, OnFileExit(), and SetStatusLabel().
    4. Update the MainMenuStrip, and MainToolbarStrip properties to return the RadMenu and RadToolStripElement.
      internal RadMenu MainMenuStrip 
          get { return radMenu1; } 
       
      internal RadToolStripElement MainToolStrip 
          get { return radToolStripElement1; } 
  7. Double click ShellLayoutViewPresenter.cs to view it’s code.
    1. Remove the method that subscribes to the StatusUpdate event.
    2. Remove the OnFileExit() method.
    3. Update the OnViewSet() method to register the RadMenu and RadToolStrip controls as UIExtensionSites.
      protected override void OnViewSet() 
          WorkItem.UIExtensionSites.RegisterSite(UIExtensionSiteNames.MainMenu, View.MainMenuStrip); 
          WorkItem.UIExtensionSites.RegisterSite(UIExtensionSiteNames.MainToolbar, View.MainToolStrip); 
  8. The ShellLayoutView is now ready.

Extending the TCEK

The items used in the RadToolStrip do not support command invokers by default. In this series of steps, we will extend the TCEK to support this feature. We will accomplish this by creating a new RadElementCommandAdapter that supports the base class of items used in the RadToolStrip. This is actually a very simple task and you can probably use the knowledge you gain here to extend support to various other Telerik controls.

  1. In the Solution Explorer, expand the Telerik.CAB.WinForms project.
  2. Expand the Commands folder.
  3. Right click RadMenuItemCommandAdapter.cs and select Copy.
  4. Right click the Commands folder and select paste.
  5. Rename the copy to RadElementCommandAdapter.cs.
  6. Double click RadElementCommandAdapter.cs to view it’s source.
    1. Update the constructors to reflect the name of the file.
    2. Update the second constructor to accept RadElements instead of RadMenuItems.
      public RadElementCommandAdapter() 
          : base() 
       
      public RadElementCommandAdapter(RadElement element, string eventName) 
          : base(element, eventName) 
    3. Update the OnCommandChanged() method to handle RadElements instead of RadMenuItems.
      protected override void OnCommandChanged(Command command) 
          base.OnCommandChanged(command); 
       
          foreach (RadElement element in this.Invokers.Keys) 
          { 
              if (command.Status != CommandStatus.Unavailable) 
              { 
                  element.Visibility = Telerik.WinControls.ElementVisibility.Visible; 
                  element.Enabled = (command.Status == CommandStatus.Enabled); 
              } 
              else 
              { 
                  element.Visibility = Telerik.WinControls.ElementVisibility.Collapsed; 
              } 
          } 
  7. In the Solution Explorer, expand the Application folder.
    1. Double click RadWindowsFormsApplication.cs to view its source.
    2. Register the RadElementCommandAdapter with the ICommandAdapterMapService.
          //Registers Command Adapters. 
          ICommandAdapterMapService mapService = this.RootWorkItem.Services.Get<ICommandAdapterMapService>(); 
          mapService.Register(typeof(RadMenuItem), typeof(RadMenuItemCommandAdapter)); 
          mapService.Register(typeof(RadTreeNode), typeof(RadTreeNodeCommandAdapter)); 
          mapService.Register(typeof(RadElement), typeof(RadElementCommandAdapter)); // this line 
  8. You have now successfully extended the TCEK to support adding invokers to RadElements.

The AssetManager Module

In this series of steps, we will create the primary module used in this application. In this module, we will extend the UIExtensionSites with our own custom menu options and toolbar buttons. We will also add CommandHandlers to handle the commands issued by the items added to the UIExtensionSites.

Creating the Module

In these steps, we will generate the AssetManager module.

  1. In the Solution Explorer, right click the source folder and select Smart Client Factory->Add Business Module (C#)…
  2. Name the new business module AssetManager and click OK.
    image
  3. Click Finish on the Add Business Module dialog.

Creating The Data

In these steps, we will create the object that will hold our “asset” data that is displayed in the grid.

  1. Right click on the AssetManager project and select Add->New Folder
    1. Name the new folder Data.
  2. Right click the Data folder and select Add->Class..
    1. Name the class Asset.
  3. Double click Asset.cs to view it’s source.
    1. Update the source code to contain properties specific to basic information about the assets we will be tracking.
      public class Asset 
          public string Name { getset; } 
          public string Description { getset; } 
  4. Build the project so our Asset class gets compiled into the assembly. This will allow us to easily bind it to a BindingSource later.

Creating the Command Names

  1. In the Solution Explorer, expand the Constants folder of the AssetManager project and double click the CommandNames.cs file to view its source.
  2. Update the source code to contain the command names we will be using in our view.
    public class CommandNames : CABExample1.AssetManager.Interface.Constants.CommandNames 
        public const string AddAsset = "AddAsset"
        public const string RemoveAsset = "RemoveAsset"
        public const string EditAsset = "EditAsset"

Extending the UIExtensionSites

  1. In the Solution Explorer, double click the ModuleController.cs file contained in the AssetManager project to view its source.
  2. Extend the MainMenu UIExtensionSite by updating the ExtendMenu() method to contain the following code.
    private void ExtendMenu() 
        RadMenuItem assetMenuItem = new RadMenuItem("Assets"); 
        this.WorkItem.UIExtensionSites[UIExtensionSiteNames.MainMenu].Add<RadMenuItem>(assetMenuItem); 
     
        RadMenuItem addAssetMenuItem = new RadMenuItem("Add Asset"); 
        this.WorkItem.Commands[CommandNames.AddAsset].AddInvoker(addAssetMenuItem, "Click"); 
                 
        RadMenuItem removeAssetMenuItem = new RadMenuItem("Remove Asset"); 
        this.WorkItem.Commands[CommandNames.RemoveAsset].AddInvoker(removeAssetMenuItem, "Click"); 
     
        RadMenuItem editAssetMenuItem = new RadMenuItem("Edit Asset"); 
        this.WorkItem.Commands[CommandNames.EditAsset].AddInvoker(editAssetMenuItem, "Click"); 
     
        assetMenuItem.Items.Add(addAssetMenuItem); 
        assetMenuItem.Items.Add(removeAssetMenuItem); 
        assetMenuItem.Items.Add(editAssetMenuItem); 
  3. Extend the MainToolbar UIExtensionSite by updating the ExtendToolStrip() method to contain the following code.
    private void ExtendToolStrip() 
        RadButtonElement buttonElement = new RadButtonElement("Add Asset"); 
        RadToolStripItem toolStripItem = new RadToolStripItem(); 
        toolStripItem.Items.AddRange(new RadItem[] { buttonElement }); 
        this.WorkItem.Commands[CommandNames.AddAsset].AddInvoker(buttonElement, "Click"); 
        this.WorkItem.UIExtensionSites[UIExtensionSiteNames.MainToolbar].Add<RadToolStripItem>(toolStripItem); 
     
        buttonElement = new RadButtonElement("Remove Asset"); 
        toolStripItem = new RadToolStripItem(); 
        toolStripItem.Items.AddRange(new RadItem[] { buttonElement }); 
        this.WorkItem.Commands[CommandNames.RemoveAsset].AddInvoker(buttonElement, "Click"); 
        this.WorkItem.UIExtensionSites[UIExtensionSiteNames.MainToolbar].Add<RadToolStripItem>(toolStripItem); 
     
        buttonElement = new RadButtonElement("Edit Asset"); 
        toolStripItem = new RadToolStripItem(); 
        toolStripItem.Items.AddRange(new RadItem[] { buttonElement }); 
        this.WorkItem.Commands[CommandNames.EditAsset].AddInvoker(buttonElement, "Click"); 
        this.WorkItem.UIExtensionSites[UIExtensionSiteNames.MainToolbar].Add<RadToolStripItem>(toolStripItem); 

The AssetListing View

  1. In the Solution Explorer, right click the Views folder of the AssetManager project and select Smart Client Factory->Add View (with presenter)…
    1. Name the view AssetListing. Make sure to check the “Create folder for the view” checkbox, then click Finish.
      image
  2. Double click AssetListing.cs to open it in the designer.
    1. Drag a RadGridView control on the the view and name it AssetListing.
    2. Click the SmartTag on the newly added RadGridView, and in the menu that appears, open the Choose DataSource combobox, then select Add Project Data Source…
      1. Select Object and click Next.
      2. Expand AssetManager, CabExample1.AssetManager.Data, and select Asset, then click Finish.
        image
    3. Update the grid properties to your liking, and so that the grid is read only, and you can not add, delete, or edit new rows.
  3. Double click IAssetListing.cs to view it’s source.
    1. Update the IAssetListing interface to contain properties referencing the RadGridView and the BindingSource.
      public interface IAssetListing 
          RadGridView GridView { get; } 
          BindingSource AssetBindingSource { get; } 
  4. Right click on AssetListing.cs and select View Code.
    1. Implement the IAssetListing interface.
      #region IAssetListing Members 
       
      public Telerik.WinControls.UI.RadGridView GridView 
          get { return radGridView1; } 
       
      public BindingSource AssetBindingSource 
          get { return assetBindingSource; } 
      #endregion 
  5. Double click AssetListingPresenter.cs to view its source.
    1. Create and assign some generic test data to the the AssetBindingSource on the view.
      List<Asset> _assets; 
      public override void OnViewReady() 
          base.OnViewReady(); 
       
          _assets = new List<Asset>(); 
       
          for (int i = 0; i < 100; i++) 
              _assets.Add(new Asset() { Name = "Asset " + i.ToString(), Description = "Description " + i.ToString() }); 
       
          View.AssetBindingSource.DataSource = _assets; 
    2. Add the AddAsset, RemoveAsset, and EditAsset command handlers. (note: the AssetDetailDialog will be created in the next section)
      [CommandHandler(CommandNames.AddAsset)] 
      public void AddAsset(object sender, EventArgs e) 
          _assets.Add(new Asset() { Name = "New Asset", Description = "New Asset Description" }); 
          View.AssetBindingSource.ResetBindings(false);             
       
      [CommandHandler(CommandNames.RemoveAsset)] 
      public void RemoveAsset(object sender, EventArgs e) 
          Asset asset = (Asset)View.GridView.SelectedRows[0].DataBoundItem; 
          _assets.Remove(asset); 
          View.AssetBindingSource.ResetBindings(false); 
       
      [CommandHandler(CommandNames.EditAsset)] 
      public void EditAsset(object sender, EventArgs e) 
          Asset asset = (Asset)View.GridView.SelectedRows[0].DataBoundItem; 
          AssetDetailDialog detailDialog = new AssetDetailDialog(asset); 
          detailDialog.ShowDialog(); 
  6. Double click ModuleController.cs to view its source.
    1. Update the AddViews() method to add our newly created view to the main workspace.
      private void AddViews() 
          AssetListing view = ShowViewInWorkspace<AssetListing>(WorkspaceNames.MainWorkspace); 

The Asset Detail Dialog

  1. In the Solution Explorer, Right click the Views folder and select Add->New Folder
    1. Name the folder Dialogs
  2. Right click the Dialogs folder and select Add->Windows Form…
    1. Name the form AssetDetailDialog
      image
  3. Drag two RadLabels from the toolbox into the designer.
    1. Set the Text property of the first label to Name.
    2. Set the Text property of the second label to Description.
  4. Drag two RadTextBoxes from the toolbox into the designer.
    1. Set the text on both of them to be blank.
    2. Select radTextBox1.
      1. In the properties window, expand (DataBindings), then the Text Property.
      2. Locate and expand Asset, then select Name.
    3. Select radTextBox2
      1. In the properties window, expand (DataBindings), then the Text Property.
      2. Expand assetBindingSource and select Description.
    4. Drag a RadButton from the toolbox into the designer.
    5. Set the text on the RadButton to OK.
  5. Set the DialogResult property of the OK button to OK.
  6. Right click the designer window and select View code.
  7. Update the constructor so that it takes an asset and sets it on assetBindingSource.
    public AssetDetailDialog(ref Asset asset) 
        InitializeComponent(); 
        assetBindingSource.DataSource = asset; 

Conclusion

Congratulations, you have now created a project that uses the RadMenu and the RadToolStrip as UIExtensionSites! Any CAB based project is a huge effort in itself, so I know how difficult it can be when you need to introduce something new to the bag of tricks. Hopefully this tutorial eased some of that difficulty for you and helped you gain a better understanding of how to use the UIExtensionSites provided by the TCEK with CAB. Next week, I will begin covering the workspaces provided with the TCEK. See you then!

 

Click here to download the source code used in this post.


Comments

Comments are disabled in preview mode.