31 October 2015

Conditionally highlighting rows in Silverlight RAD grid using MVVM approach

In today's post we will discuss how to conditionally highlight rows in Telerik Rad-Grid for Silverlight.

The Telerik RadGrid is a control equivalent to the traditional ‘Gridview’ in vanilla Silverlight. The implementation for the requirement is very easy in traditional code behind using the available events and objects of Telerik RadGrid for Silverlight.  The approach is slightly different in MVVM approach. This post details how to implement this requirement from within the realm of MVVM pattern.

Approach

  • Conditionally highlighting of rows in Telerik Rad-Grid can be achieved by creating custom cell style selector. 
  • This is done by creating a class for custom cell style selector which derives from Telerik.Windows.Controls.StyleSelector. 
  • This class will have the logic for choosing the cell style based on business logic. 
  • This custom created style can then be used in XAML as a ‘Static resource’. 
  • When rad-grid row is loaded, the code written in cell style selector class is executed and appropriate style is applied to the row.
  • This approach helps in achieving the functionality without writing code in code-behind class.

Implementation

Step 1 - Creating class for cell style selector

Step 1.1 - Create a class which inherits from Telerik.Windows.Controls.StyleSelector. Let’s name this class as ‘RadGridCellStyleSelector’. So declaration of class will be as follows – 

{
    public class RadGridCellStyleSelector : StyleSelector
    {
   
    }
}

Step 1.2 - Add two auto implemented properties of type ‘System.Windows.Style’ which will define the style of rows in normal and highlighted modes.

/// <summary>
/// Gets or sets style to apply on the cells in the highlighted row.
/// </summary>
public Style HighlightedCellStyle { get; set; }

/// <summary>
/// Gets or sets style to apply on the cells in the normal non-highlighted row.
/// </summary>
public Style NormalCellStyle { get; set; }

Step 1.3 - Override the ‘SelectStyle’ method of ‘StyleSelector’ class from which ‘RadGridCellStyleSelector’ class has been derived.

/// <summary>
/// Selects the style to apply to the given row.
/// </summary>
/// <param name="item">The row that the cell belongs to.</param>
/// <param name="container">The parameter is not used.</param>
/// <returns>The style to apply to the cell.</returns>
public override Style SelectStyle(object item, DependencyObject container)
{
    //Get the data for row which will be bound
    var row = item as RowDataModel;
    if (row == null)
    {
        return null;
    }

    return row.Status == "True" ? HighlightedCellStyle : NormalCellStyle;
}
  • Here, ‘item’ will give the data for the row which will be bound to the grid. In sample code, this is of type ‘RowDataModel’. 
  • This can be retrieved and then condition is checked for the required property (Status). 
  • Based on value of the property, the required cell style is chosen and returned. 
  • The highlighted logic can be customized according to actual requirement.
Step 2 - Using custom cell style selectors in XAML

Step 2.1 - Declare the namespace in which custom cell style selector class has been declared. In this case, it is ‘MyProject.RadGridCustomStyles’.

<UserControl x:Class="MyProject"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"
    mc:Ignorable="d"
    xmlns:custom="clr-namespace:MyProject.RadGridCustomStyles"
           d:DesignHeight="300" d:DesignWidth="1000">

Step 2.2 - Now we define the rad grid cell style as a resource 

<UserControl.Resources> 
    <ResourceDictionary>
       <custom:RadGridCellStyleSelector x:Key="MyRadGridCellStyleSelector"
            NormalCellStyle="{StaticResource GridViewNormalCellStyle}"
            HighlightedCellStyle="{StaticResource GridViewHighlightedCellStyle}"/>
    </ResourceDictionary>
</UserControl.Resources>

Here – 
  • RadGridCellStyleSelector – is name of the class
  • NormalCellStyle – Property of the class of type Style
  • HighlightedCellStyle – Property of the class of type Style
Step 2.3 - The styles ‘GridViewNormalCellStyle’ and ‘GridViewHighlightedCellStyle’ are the actual styles that will be defined for XAML in style sheet

<Style x:Key="GridViewNormalCellStyle" TargetType="telerik:GridViewCell">
    <Setter Property="Background" Value="White" />
    <Setter Property="VerticalContentAlignment" Value="Top"/>
    <Setter Property="HorizontalContentAlignment" Value="Left"/>       
</Style>
<Style x:Key="GridViewHighlightedCellStyle" TargetType="telerik:GridViewCell">
    <Setter Property="Background" Value="Yellow" />
    <Setter Property="VerticalContentAlignment" Value="Top"/>
    <Setter Property="HorizontalContentAlignment" Value="Left"/>
</Style>

Here the styles can be customized according to need. In this example, for the highlighted cells, the background colour has been changed from normal white colour to ‘Yellow’

Step 2.4 - In telerik rad grid column, specify the CellStyleSelector as ‘RadGridCellStyleSelector’.

<telerik:GridViewDataColumn Width="150" HeaderTextAlignment="Center"                                          CellStyleSelector="{StaticResource RadGridCellStyleSelector}" TextAlignment="Left"                                           />
Advantages
  • The advantage of using this approach is that you are able to stick to MVVM pattern with no code-behind involved. 
  • The logic is cleanly separated in a class while the actual styles are still present in your style-sheet.
  • The business logic and styles have clean separation leading to easier maintenance.


30 October 2015

Selecting multiple checkboxes in Silverlight Telerik RAD grid using MVVM approach

In today's post, we will discuss about selecting multiple rows in a Telerik Rad-Grid and then performing action on selected rows. This needs to be achieved using MVVM approach as project follows MVVM pattern.

To handle multiple selections of rows in rad-grid using MVVM pattern, ‘Silverlight behaviors’ can be used. The main use of ‘Silverlight Behaviors’ is to provide additional functionalities and extensibility to controls without writing code in the code-behind. This helps in sticking to MVVM pattern more religiously.

The advantage of using this approach is that you are able to stick to MVVM pattern with no code-behind involved.

Step 1 - Creating class for implementing behavior

Step 1.1 - Create a class which inherits from System.Windows.Interactivity.Behavior. Let’s name this class as ‘RadGridMultipleSelectBehavior’.

So declaration of class will be as follows –

namespace MyProject.CustomRadGridBehaviors
{

public class RadGridMultipleSelectBehavior : Behavior<RadGridView>
{

}
}

Here ‘RadGridView’ is the associated dependency object for which the behavior is to be implemented. In this class, various properties and events of ‘RadGridView’ can be easily accessed as in code-behind. But since this code is not written in code-behind we are de-coupled from code-behind model.

Step 1.2 - Declare a dependency property which will store the selected items in the rad-grid. This dependency property then needs to be registered with rad-grid. This will link the property with the rad-grid.

public static readonly DependencyProperty SelectedItemsProperty =
DependencyProperty.Register("SelectedItems",
typeof(INotifyCollectionChanged),
typeof (RadGridMultipleSelectBehavior),
null);

Step 1.3 - Declare a property of type RadGridView. In the get accessor of the property, return associated rad-grid as ‘AssociatedObject’. This is an inbuilt property of the behavior object.

        private RadGridView Grid
        {
            get { return AssociatedObject; }
        }

Step 1.4 - Override ‘OnAttached’ method of ‘Behavior’ class. This will help to specify the actions that should be performed when this behavior is attached to the rad-grid. In this method, wire-up an event handler to the rad-grid selected items collection changed property. 

        protected override void OnAttached()
        {
            base.OnAttached();
            Grid.SelectedItems.CollectionChanged += SelectedItemsCollectionChanged;
        }

CollectionChanged event is fired in following scenarios – 
  • Item is added to the collection (Row is selected in rad-grid)
  • Item is removed from the collection (Row is unselected in rad-grid)
  • Collection itself changes completely (Page change in rad-grid)
Step 1.5 - Once event handler is wired with event, implement the event handler. All of these conditions are handled in SelectedItemsCollectionChanged event handler as follows 






















Here, when item is removed from collection or collection changes completely, e.OldItems will not be null. It will have all the items that were previously selected but now unselected. So these items can be removed from ‘SelectedItems’. 
When item is added to collection, e.NewItems will not be null. Hence newly selected items will be added to the ‘SelectedItems’ collection. If the items are being added for the first time, the ‘SelectedItems’ collection will be created. 

Step 2 - Using the behavior class in XAML as behavior

Once this class is created, it can be used in XAML as rad-grid behavior.

Step 2.1 - First add namespace for Microsoft interactivity and our rad grid behavior class as highlighted below – 

<UserControl x:Class="MyProject"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"
    mc:Ignorable="d"
    xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"   
    xmlns:custom="clr-namespace:MyProject.CustomRadGridBehaviors"
    d:DesignHeight="300" d:DesignWidth="1000">

Step 2.2 - Once this is done, behavior class can be easily used in rad-grid as follows – 

<telerik:RadGridView Name="MyRadGridView">
   <i:Interaction.Behaviors>
      <custom:RadGridMultipleSelectBehavior
          SelectedItems="{Binding Path=SelectedItems,Mode=TwoWay}"/>               
   </i:Interaction.Behaviors>           
</telerik:RadGridView>

Step 2.3 - Now declare the ‘SelectedItems’ property in view model as follows – 

public ObservableCollection<object> SelectedItems { set; get; }

Step 2.4 - This property will now be updated from view whenever any row is selected or unselected in the rad-grid. This property can then be used in your view model logic as required. 

29 October 2015

Performance issue while reading/writing large excel files using OpenXML SDK

Recently we faced performance issue while reading/writing large excel files using Open XML SDK. The code used to work fine when excel file has small number of rows. But the execution time used to increase exponentially as the number of rows increases. When we analyzed the code and researched over internet, we found that the problem lies with the way we were using Open XML SDK.

There are two approaches to use Open XML SDK -
  1. Open XML SDK DOM Approach
  2. Open XML SDK SAX-Like Approach

Open XML SDK DOM Approach

This approach works by reading every cell value of every row present in excel. This is generally the standard way on using Ope nXML SDK. It works well when the number of rows in excel file are less. However as the number of rows increases, the memory utilized by these methods increases leading to performance deterioration. 

Example of DOM Approach

using (SpreadsheetDocument excelDocument = SpreadsheetDocument.Open(excelFilePathAndName, true))
{
    WorkbookPart excelWorkBook = excelDocument.WorkbookPart;
    WorksheetPart excelWorksheetPart = excelWorkBook.WorksheetParts.First();
    SheetData exceSheetData = excelWorksheetPart.Worksheet.Elements<SheetData>().First();
    foreach (Row excelRow in exceSheetData.Elements<Row>())
    {
        foreach (Cell excelCell in excelRow.Elements<Cell>())
        {
            string excelCellValue = excelCell.CellValue.Text;
            Console.WriteLine(excelCellValue);
        }
    }

}

Open XML SDK SAX-Like Approach

This approach works by utilizing methods OpenXMLReader and OpenXMLWriter of Open XML SDK. These method uses the SAX approach of reading an excel file. They read the excel as an XML tree but do not load the entire tree in memory leading to better performance. 

Example of SAX-Like Approach -  

string excelFilePathAndName = "<Path of excel file with name>";

using (SpreadsheetDocument excelDocument = SpreadsheetDocument.Open(excelFilePathAndName, true))
{
    WorkbookPart excelWorkBook = excelDocument.WorkbookPart;
    WorksheetPart excelWorksheetPart = excelWorkBook.WorksheetParts.First();
    OpenXmlReader excelReaderreader = OpenXmlReader.Create(excelWorksheetPart);
    while (excelReaderreader.Read())
    {
        if (excelReaderreader.ElementType == typeof(CellValue))
        {
            string excelCellValue = excelReaderreader.GetText();
            Console.WriteLine(excelCellValue);
        }
    }

}

To conclude, for better performance while reading large excel files, use SAX-Like approach by utilizing OpenXMLReader and OpenXMLWriter classes.

28 October 2015

Creating and managing PST files using Outlook Add-in

Outlook add-ins provides an easier way to add custom tabs and buttons to your Outlook toolbar which can perform a custom task or functionality that is originally not available in Outlook.

Example of such a requirement can be to have a button which can file an email message in a new or existing PST under appropriate new or existing folders based on certain special text in email subject or body. If the PST or folder inside PST does not exist, it should get created automatically.

This can be done using ‘VSTO 3.0 Outlook 2007’ add-in. This is available in Visual Studio 2008 as Outlook 2007 Add-in.

Implementation

Step 1 - Create a project of type – ‘Office --> Outlook 2007 Add-in’ in Visual Studio 2008. You can choose language as either C# or VB.NET. In our case, we have used VB.NET.




























Step 2 - Now add an item of type ‘Ribbon (Visual Designer)’ in the project
























Step 3 - This ribbon creates a new ‘Custom Tab’ in your outlook ribbon bar (toolbar). You can rename the ribbon from ‘Custom Tab’ to ‘Auto File’. You can then add a ‘Office Ribbon Control – Box’ on the ribbon and then add ‘Office Ribbon Control – Button’.

























Step 4 - Double click the button added on ribbon. This will auto-generate the click function for that button. The click function will be something like this – 

Private Sub FileToPST_Click(ByVal sender As System.Object, ByVal e As Microsoft.Office.Tools.Ribbon.RibbonControlEventArgs) Handles FileToPST.Click
End Sub

Here FileToPST_Click is the name of the function and it handles the Click event of button FileToPST

Step 5 - Now in this function, we can write code to create/manage PSTs and move email in them.

1.    Create object of type Outlook.Application. This object will act as handle for outlook application

Dim OL As Outlook.Application
OL = CType(GetObject(, "Outlook.Application"), Outlook.Application)

2.    Create object of type Outlook.MailItem. This object will act as handle for current outlook mail.

Dim MI As Outlook.MailItem
MI = OL.ActiveInspector.CurrentItem

3.    Create object of type Outlook.Namespace. This object is required to refer to MAPI namespace and outlook PST will be created under this namespace. This namespace contains both current Inbox and all the PSTs.

Dim NS As Outlook.NameSpace
NS = OL.GetNamespace("MAPI")

4.    Create object of type Outlook.Store. This object will act as handle for the PST where we will store the email.

Dim store As Outlook.Store = Nothing

5.    You can refer to subject and body of email using following code –

         mailSubject = MI.Subject
         
   mailBody = MI.Body

6.    Now create or open an existing PST using following code

NS.AddStore(PSTFolderPath)

7.    Once PST is created or opened, use following code to loop through all the PSTs under namespace and then refer to it.

            For Each store In NS.Stores
                If store.FilePath = PSTFolderPath Then
                    Exit For
                End If
   Next

8.    At the end of this code, object store will be referring to required PST (new or existing).

9.    Now you need to refer to root folder of your PST first. To do this, use following code –

          Dim rootFolder As Outlook.MAPIFolder
          rootFolder = store.GetRootFolder()

10. Once, you have access to the root folder, you can either access sub-folders under it or create new sub-folders under it.

11. To access a sub-folder named ‘MyFolder’ under your root folder in PST, you can use following code –

Dim subFolder As Outlook.Folder
         For Each subFolder In rootFolder.Folders

            If subFolder.Name = "MyFolder" Then
                  Exit For
            End If
Next

12. If you would like to create a new folder under root folder with name ‘MyNewFolder’, you can use following code –

rootFolder.Folders.Add("MyNewFolder")

13. Finally, if you would like to move or copty your email message in this folder, you can use following code

                                  i.    For moving - MI.Move(subFolder)
                                 ii.    For copying - MI.Copy(subFolder)

Here MI object refers to current mail item/email message.

14. Once, all the required operations have been performed, you can close the PST by removing it from MAPI namespace. This can be done using following code


         NS.RemoveStore(rootFolder)


Here I have provided very basic example of moving/copying an email from Inbox to your existing/new PST in an existing/new folder. Further logic can be created as per requirement like moving/copying mail based on certain text in Subject/Body of email. There are no limitations of type of logic that can be written. This overcomes the limitations in ‘Email Rules’ provided by Outlook.

Deployment

Lets name the sample application has as ‘Oscar_OutlookAddIn’

For creating installer package, following steps can be followed:-

Build --> Publish Oscar_OutlookAddin


















It will ask for location where you will like to create the installer. Enter or Browse the location and then click ‘Next’ button.



On the next page, select the middle option – ‘From a UNC path or file share’ and click Next































Last screen will appear now showing you the location where installer package will be created. Click on ‘Finish’ button.































This will create the installer at the specified location.









Now you can distribute this complete folder to client machines for installation. User can click on ‘setup.exe’ to install the add-in. Once add-in is installed, whenever any email message is opened, a new button called ‘Auto-File’ will appear in a separate ribbon like this – 




Outlook add-ins provides us the flexibility to create custom buttons in our Outlook which cannot be fulfilled by existing functionality in Outlook.