Click here to Skip to main content
Click here to Skip to main content

Customize Tab Control in Silverlight (create tab control with side bar)

, 22 Dec 2011
Rate this:
Please Sign up or sign in to vote.
Creating TabControl with SideMenu and SideBar

Introduction

The TabControl control brings flexibility to your websites navigation by allowing you to create a set of Tabs that can be used to organize page content.

Background

TabControl is Silverlight toolkit control, so first, you have to install the latest toolkit download from here.

After installing the toolkit, you will see TabControl in your toolbox.

In Silverlight Development Environment, it is difficult to change the layout of TabControl.

Sometimes, we have a requirement to customize our tab control layout, so we need to create a custom template for TabControl and TabItems.

In this article, we walk-through how to Create Sidebar control with TabControl on the right of side bar and show/hide side bar.

Using the Code

Step 1: Create Custom ScalePanel Control for Side bar

ScalePanel.cs

  public class ScalePanel : Panel
    {
        #region ScaleXProperty
        public Double ScaleX
        {
            get { return (Double)GetValue(ScaleXProperty); }
            set { SetValue(ScaleXProperty, value); }
        }
        public static readonly DependencyProperty ScaleXProperty =
            DependencyProperty.Register("ScaleX", typeof(Double), typeof(ScalePanel), 
            new PropertyMetadata(1.0d, new PropertyChangedCallback(ScaleXChanged)));

        public static void ScaleXChanged(DependencyObject sender, 
                                    DependencyPropertyChangedEventArgs e)
        {
            ScalePanel obj = sender as ScalePanel;
            if (obj != null)
            {
                obj.OnScaleXChanged(e);
            }
        }
        private void OnScaleXChanged(DependencyPropertyChangedEventArgs e)
        {
            InvalidateMeasure();
        }
        #endregion

        #region ScaleYProperty
        public Double ScaleY
        {
            get { return (Double)GetValue(ScaleYProperty); }
            set { SetValue(ScaleYProperty, value); }
        }

        public static readonly DependencyProperty ScaleYProperty =
            DependencyProperty.Register("ScaleY", typeof(Double), typeof(ScalePanel), 
            new PropertyMetadata(1.0d, new PropertyChangedCallback(ScaleYChanged)));

        public static void ScaleYChanged(DependencyObject sender, 
                                          DependencyPropertyChangedEventArgs e)
        {
            ScalePanel obj = sender as ScalePanel;
            if (obj != null)
            {
                obj.OnScaleYChanged(e);
            }
        }

        private void OnScaleYChanged(DependencyPropertyChangedEventArgs e)
        {
            InvalidateMeasure();
        }
        #endregion

        protected override Size MeasureOverride(Size availableSize)
        {
            Size finalSize = new Size();

            if (Children.Any())
            {
                UIElement child = Children.First();
                child.Measure(availableSize);
                finalSize.Width = Math.Min(child.DesiredSize.Width, availableSize.Width);
                finalSize.Height = Math.Min(child.DesiredSize.Height, availableSize.Height);
            }

            finalSize.Width = finalSize.Width * ScaleX;
            finalSize.Height = finalSize.Height * ScaleY;

            return finalSize;
        }

        protected override Size ArrangeOverride(Size finalSize)
        {
            if (Children.Any())
            {
                UIElement child = Children.First();
                child.Arrange(new Rect(0, 0, finalSize.Width, finalSize.Height));
            }

            return finalSize;
        }
    } 

In this code, you notice that ScaleXProperty and ScaleYProperty dependency properties are defined.

So the question arises as to what is DependencyProperty? And why do we need to use it?

I give you a brief description to make you aware about DependencyProperty.

DependencyProperty

Dependency Property is like any other property, but can hold a default value, with built in mechanism for property value validation and automatic notification for changes in property value (for anyone listening to property value - especially UI) and any binding in Silverlight is binded to a Dependency Property.

Dependency properties are properties that are registered with the Silverlight property system by calling the DependencyProperty.Register method.

The purpose of dependency properties is to provide a way to compute the value of a property based on the value of other inputs.

DependencyObject defines the base class that can register and own a dependency property.

You can go into detail with an example by following this link.

So both scaleY and ScaleY properties scale the panel with content.

There are two override methods defined, one is MeasureOverride and other is ArrangeOverride.

  • MeasureOverride

    Provides the behavior for the Measure pass of Silverlight layout.

    This method has a default implementation that performs built-in layout for most Silverlight FrameworkElement classes.

    So in our code, it customizes the Measure pass logic for a custom panel implementation and it performs the following task.

    1. Iterates over children.
    2. For each child, calls Measure, using a Size that makes sense based on how the panel logic treats the number of children and its own known size limit.
    3. Returns its size (determines it needs during layout, based on its calculations of child object allotted sizes).

    You can go into detail by looking at an example at this link.

  • ArrangeOverride

    Provides the behavior for the Arrange pass of Silverlight layout. In simple words, it arranges the content of a FrameworkElement. ArrangeOverride customizes the Arrange pass.

    1. Iterates over children.
    2. For each child, calls Arrange, using a Rect where Height and Width are based on DesiredSize, and X and Y are based on logic that is specific to the panel.
    3. Returns its size (the actual size that is used after the element is arranged in layout)

    For Silverlight/WPF, the technique by which elements are sized and positioned in a layout is divided into two steps: a Measure pass, and then an Arrange pass.

    You can go into detail by looking at an example at this link.

Step 2: Add namespace in your UserControl

  xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
  xmlns:toolkit="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit"       
  xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
  xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions" 
  1. System.windows.Interactivity provides Event Trigger on control to perform action on event fire.
  2. Interaction provides ControlStoryboardAction with EventTrigger.
  3. Toolkit is used for Transform Layout of Control.

Step 3: Create Template for TabItem

 <ControlTemplate x:Key="RightMenuTabItem"
                         TargetType="sdk:TabItem">
            <Border>
                <VisualStateManager.VisualStateGroups>
                    <VisualStateGroup x:Name="CommonStates">
                        <VisualState x:Name="Normal" />
                        <VisualState x:Name="MouseOver">
                            <Storyboard>
                                <DoubleAnimation Storyboard.TargetName="
                                	TabHeaderHighlightBackgroundBorder"
                                                 Storyboard.TargetProperty="Opacity"
                                                 To="1"
                                                 Duration="0:0:0.25" />
                                <ObjectAnimationUsingKeyFrames Duration="00:00:00.25"
                                                 Storyboard.TargetName="ContControl"
                                                 Storyboard.TargetProperty="Foreground">
                                    <DiscreteObjectKeyFrame KeyTime="00:00:00">
                                        <DiscreteObjectKeyFrame.Value>
                                            <Color>Black</Color>
                                        </DiscreteObjectKeyFrame.Value>
                                    </DiscreteObjectKeyFrame>
                                </ObjectAnimationUsingKeyFrames>
                                <ObjectAnimationUsingKeyFrames Duration="00:00:00.25"
                                                 Storyboard.TargetName="TabHeaderBackgroundBorder"
                                                 Storyboard.TargetProperty="BorderThickness">
                                    <DiscreteObjectKeyFrame KeyTime="00:00:00">
                                        <DiscreteObjectKeyFrame.Value>
                                            <Thickness>1 1 0 0</Thickness>
                                        </DiscreteObjectKeyFrame.Value>
                                    </DiscreteObjectKeyFrame>
                                </ObjectAnimationUsingKeyFrames>
                            </Storyboard>
                        </VisualState>
                    </VisualStateGroup>
                    <VisualStateGroup x:Name="SelectionStates">
                        <VisualState x:Name="Unselected" />
                        <VisualState x:Name="Selected">
                            <Storyboard>
                                <DoubleAnimation Storyboard.TargetName="
                                		TabHeaderSelectedBackgroundBorder"
                                                 Storyboard.TargetProperty="Opacity"
                                                 To="1"
                                                 Duration="0:0:0.25" />
                                <ObjectAnimationUsingKeyFrames Duration="00:00:00.25"
                                                 Storyboard.TargetName="ContControl"
                                                 Storyboard.TargetProperty="Foreground">
                                    <DiscreteObjectKeyFrame KeyTime="00:00:00">
                                        <DiscreteObjectKeyFrame.Value>
                                            <Color>Black</Color>
                                        </DiscreteObjectKeyFrame.Value>
                                    </DiscreteObjectKeyFrame>
                                </ObjectAnimationUsingKeyFrames>
                                <ObjectAnimationUsingKeyFrames Duration="00:00:00.25"
                                                  Storyboard.TargetName="
                                                  TabHeaderBackgroundBorder"
                                                  Storyboard.TargetProperty="BorderThickness">
                                    <DiscreteObjectKeyFrame KeyTime="00:00:00">
                                        <DiscreteObjectKeyFrame.Value>
                                            <Thickness>1 1 0 0</Thickness>
                                        </DiscreteObjectKeyFrame.Value>
                                    </DiscreteObjectKeyFrame>
                                </ObjectAnimationUsingKeyFrames>
                            </Storyboard>
                        </VisualState>
                    </VisualStateGroup>
                </VisualStateManager.VisualStateGroups>
                <toolkit:LayoutTransformer x:Name="layoutTransformer">
                    <toolkit:LayoutTransformer.LayoutTransform>
                        <RotateTransform Angle="90" />
                    </toolkit:LayoutTransformer.LayoutTransform>
                    <Border x:Name="TabHeaderBackgroundBorder"
                            RenderTransformOrigin="0.5,0.5"
                            BorderBrush="Black"
                            BorderThickness="1,1,0,1"
                            Background="{StaticResource TabHeaderBackground}">
                        <Grid>
                            <Border x:Name="TabHeaderHighlightBackgroundBorder"
                                    Opacity="0"
                                    Background="{StaticResource TabHeaderHighlightBackground}" />
                            <Border x:Name="TabHeaderSelectedBackgroundBorder"
                                    Opacity="0"
                                    Background="{StaticResource TabHeaderSelectedBackground}" />
                            <ContentControl Content="{TemplateBinding Header}"
                                            HorizontalContentAlignment="Center"
                                            VerticalContentAlignment="Center"
                                            Margin="16,10,16,10"
                                            FontFamily="Verdana"
                                            FontSize="15"
                                            Foreground="White"
                                            FontWeight="Bold"
                                            Cursor="Hand"
                                            x:Name="ContControl" />
                        </Grid>
                    </Border>
                </toolkit:LayoutTransformer>
            </Border>
        </ControlTemplate>

The above control template provides style and template for TabItems.

VisualStateManager manages states and the logic for transitioning between states for controls.

Created customStates which defines MouseOver, Normal and Selected visualstate object for each TabItems. When user puts mouse over the tab items, its background color changes to yellow and on mouse leave it will go back to red color.

 <toolkit:LayoutTransformer.LayoutTransform>
                        <RotateTransform Angle="90" />
                    </toolkit:LayoutTransformer.LayoutTransform> 

The above snippet rotates TabItems from horizontal to Vertical.

Step 4 : Create Template for TabControl

 <ControlTemplate x:Key="RightMenuTabControl"
                         TargetType="sdk:TabControl">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto" />
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="Auto" />
                </Grid.ColumnDefinitions>
                <Grid Grid.Column="0">
                    <Button Template="{StaticResource PolygonButton}"
                            x:Name="CloseCall"
                            Cursor="Hand">
                        <Polyline HorizontalAlignment="Center"
                                  VerticalAlignment="Center"
                                  Stroke="Black"
                                  StrokeThickness="2"
                                  Points="0,0 4,4 0,8" />
                        <i:Interaction.Triggers>
                            <i:EventTrigger EventName="Click">
                                <ei:ControlStoryboardAction ControlStoryboardOption="Play">
                                    <ei:ControlStoryboardAction.Storyboard>
                                        <Storyboard>
                                            <DoubleAnimation Storyboard.TargetName=
                                                             "TabContentScalePanel"
                                                             Storyboard.TargetProperty="Width"
                                                             From="300"
                                                             To="0"
                                                             Duration="00:00:00.25" />
                                            <ObjectAnimationUsingKeyFrames Duration="00:00:00.25"
                                                            Storyboard.TargetName="CloseCall"
                                                            Storyboard.TargetProperty="Visibility">
                                                <DiscreteObjectKeyFrame KeyTime="00:00:00">
                                                    <DiscreteObjectKeyFrame.Value>
                                                        <Visibility>Collapsed</Visibility>
                                                    </DiscreteObjectKeyFrame.Value>
                                                </DiscreteObjectKeyFrame>
                                            </ObjectAnimationUsingKeyFrames>
                                            <ObjectAnimationUsingKeyFrames Duration="00:00:00.25"
                                                           Storyboard.TargetName="OpenCall"
                                                           Storyboard.TargetProperty="Visibility">
                                                <DiscreteObjectKeyFrame KeyTime="00:00:00">
                                                    <DiscreteObjectKeyFrame.Value>
                                                        <Visibility>Visible</Visibility>
                                                    </DiscreteObjectKeyFrame.Value>
                                                </DiscreteObjectKeyFrame>
                                            </ObjectAnimationUsingKeyFrames>
                                        </Storyboard>
                                    </ei:ControlStoryboardAction.Storyboard>
                                </ei:ControlStoryboardAction>
                            </i:EventTrigger>
                        </i:Interaction.Triggers>
                    </Button>                   
                </Grid>
                <Border Grid.Column="1"
                        x:Name="TabContent">
                    <control:ScalePanel x:Name="TabContentScalePanel"
                                        Width="300">
                        <Grid>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="60" />
                                <RowDefinition Height="*" />
                            </Grid.RowDefinitions>
                            <Border Grid.RowSpan="2">
                                <Border.Background>
                                    <RadialGradientBrush Center="0.5,0"
                                                         GradientOrigin="0.5,0"
                                                         RadiusX="0.6"
                                                         RadiusY="0.2">
                                        <GradientStop Color="#FFFFCA3C"
                                                      Offset="1" />
                                        <GradientStop Color="#FFFFFFD5" />
                                    </RadialGradientBrush>
                                </Border.Background>
                            </Border>
                            <Border Grid.RowSpan="2">
                                <Border.Background>
                                    <RadialGradientBrush Center="0.5,1"
                                                         GradientOrigin="1,0"
                                                         RadiusX="1"
                                                         RadiusY="0.8"
                                                         Opacity="0.25">
                                        <GradientStop Color="#FFFFCA3C"
                                                      Offset="1" />
                                        <GradientStop Color="#FFFFFFD5"
                                                      Offset="1" />
                                    </RadialGradientBrush>
                                </Border.Background>
                            </Border>
                            <Border Grid.Row="0"
                                    VerticalAlignment="Top"
                                    HorizontalAlignment="Stretch"
                                    Margin="0,5,10,15">
                                <Grid>
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="*" />
                                    </Grid.ColumnDefinitions>
                                    <TextBlock Grid.Column="0"
                                               HorizontalAlignment="Center"
                                               Text="Common Part" />
                                </Grid>
                            </Border>
                            <Border Grid.Row="1"
                                    VerticalAlignment="Stretch">
                                <Grid>
                                    <ContentPresenter x:Name="ContentRight"
                                                      HorizontalAlignment="Stretch"
                                                  VerticalAlignment="Stretch"></ContentPresenter>
                                </Grid>
                            </Border>
                        </Grid>
                    </control:ScalePanel>
                </Border>
                <Grid Grid.Column="2">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="*" />
                    </Grid.RowDefinitions>
                    <ItemsPresenter Grid.Row="0" />
                </Grid>
            </Grid>
        </ControlTemplate> 

The above ControlTemplate creates Polygon button to show/hide panel (side bar) and style for TabControl background to set GradientColor.

I created one Trigger for Side bar control and storyboard for animation.

On button click, it executes trigger to show/hide side bar with doubleAnimation.

<DoubleAnimation Storyboard.TargetName="TabContentScalePanel"
       Storyboard.TargetProperty="Width"
       From="300"
       To="0"
       Duration="00:00:00.25" />

This code describes how to animate scalepanel and set width from 300 to 0.

Step 5: Drag & Drop TabControl into your Page

 <sdk:TabControl x:Name="MenuItemsTabControl"
                    TabStripPlacement="Right"
                    UseLayoutRounding="True"
                    HorizontalContentAlignment="Stretch"
                    VerticalContentAlignment="Top"
                    Padding="0"
                    Margin="0">
        <sdk:TabControl.Resources>
            <Style TargetType="sdk:TabItem">
                <Setter Property="Template"
                        Value="{StaticResource RightMenuTabItem}" />
            </Style>
            <Style TargetType="sdk:TabControl">
                <Setter Property="Template"
                        Value="{StaticResource RightMenuTabControl}" />
            </Style>
        </sdk:TabControl.Resources>
    </sdk:TabControl> 

In the above code, I am applying style and Template to TabControl and TabItems.

Step 6: Switch to ViewModel, Create HeaderViewModel

For notify property on change, download Silverlight.Extensions.dll from here and add a reference into your project.

It will add ViewModelBase class which inherits from INotifyPropertyChanged for propertyChangeNotification.

ViewModelBase class adds methods for RegisterPropertyChangeCallback and processes the child element.

HeaderViewModel.cs

  public class HeaderViewModel : ViewModelBase
    {
        public String Header { get; set; }

        public HeaderViewModel()
        { }
        public HeaderViewModel(String header)
        {
            Header = header;
        }
    } 

In the above class, I created Header property to set header on TabItems.

Step 7: Create ViewModels for Each TabItems

DepartmentViewModel.cs

 public class DepartmentViewModel : HeaderViewModel
    {
        protected Department Department { get;  set; }

        public string DepartmentName
        {
            get { return Department.DepartmentName; }
            set
            {
                Department.DepartmentName = value;
                RaisePropertyChanged(() => DepartmentName);
            }
        }
        public string DepartmentCode
        {
            get { return Department.DepartmentCode; }
            set
            {
                Department.DepartmentCode = value;
                RaisePropertyChanged(() => DepartmentCode);
            }
        }

        public DepartmentViewModel()
            : base("Department")
        {
            Department = new Department() { DepartmentName = "Production", 
                                            DepartmentCode = "123" };
        }
    } 

In the above code, I created a wrapper for Department class which defines properties from department class and raises a property that notifies to view on change.

The same way create a ViewModel for Employee and Product class to bind properties to view.

Step 8: Create TabPropertiesViewModel which holds all viewmodels added into Items collection

TabPropertiesViewModel.cs

 public class TabPropertiesViewModel : ViewModelBase
    {
        private DepartmentViewModel _departmentViewModel;
        public DepartmentViewModel DepartmentViewModel
        {
            get { return _departmentViewModel; }
            set
            {
                _departmentViewModel = value;
                RaisePropertyChanged(() => DepartmentViewModel);
            }
        }
        private EmployeeViewModel _employeeViewModel;

        public EmployeeViewModel EmployeeViewModel
        {
            get { return _employeeViewModel; }
            set
            {
                _employeeViewModel = value;
                RaisePropertyChanged(() => EmployeeViewModel);
            }
        }

        private ProductViewModel _productViewModel;

        public ProductViewModel ProductViewModel
        {
            get { return _productViewModel; }
            set
            {
                _productViewModel = value;
                RaisePropertyChanged(() => ProductViewModel);
            }
        }

        public ObservableCollection<HeaderViewModel> Items { get; set; }

        public TabPropertiesViewModel()
        {
            DepartmentViewModel = ProcessChild(new DepartmentViewModel());
            EmployeeViewModel = ProcessChild(new EmployeeViewModel());
            ProductViewModel = ProcessChild(new ProductViewModel());

            Items = new ObservableCollection<HeaderViewModel>{ 
                DepartmentViewModel,
                EmployeeViewModel,
                ProductViewModel,            
            };
        }
    }

I created Properties for each view model.

I have created a collection of HeaderViewModels because it is base class for all view models.

In constructor of class, I create an instance of each view model and added it into item collection.

Step 9: Create Views for Viewmodel

  • DepartmentView.xaml
  • EmployeeView.xaml
  • ProductView.xaml

In the above three views, I bind view model properties to view.

TabPropertiesView.xaml

 <Grid x:Name="LayoutRoot"
          Background="White">
        <controls:SideMenuControl ItemsSource="{Binding Items}" />
    </Grid>

Place SideMenuControl.xaml into UserControl by adding a reference (i.e. xmlns:controls="clr-namespace:SideMenuTabControl.Controls") and bind itemsSource from ViewModel.

Step 10: Binding TabItes to TabControl into SideMenuControl

SideMenuControl.xaml.cs

  public partial class SideMenuControl : UserControl
    {
        #region ItemsSourceProperty
        public IEnumerable<HeaderViewModel> ItemsSource
        {
            get { return (IEnumerable<HeaderViewModel>)GetValue(ItemsSourceProperty); }
            set { SetValue(ItemsSourceProperty, value); }
        }

        public static readonly DependencyProperty ItemsSourceProperty =
            DependencyProperty.Register("ItemsSource", typeof(IEnumerable<HeaderViewModel>), 
            typeof(SideMenuControl), new PropertyMetadata(null, 
            new PropertyChangedCallback(ItemsSourceChanged)));

        public static void ItemsSourceChanged
            (DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            SideMenuControl obj = sender as SideMenuControl;
            if (obj != null)
            {
                obj.OnItemsSourceChanged(e);
            }
        }

        private void OnItemsSourceChanged(DependencyPropertyChangedEventArgs e)
        {
            MenuItemsTabControl.ItemsSource = BuildItemsSource(ItemsSource);
            MenuItemsTabControl.SelectedIndex = 0;
        }

        private IEnumerable BuildItemsSource(IEnumerable<HeaderViewModel> ItemsSource)
        {
            Dictionary<Type, UserControl> views = new Dictionary<Type, UserControl>() { 
                { typeof(EmployeeViewModel), new EmployeeView() },
                { typeof(DepartmentViewModel), new DepartmentView() },
                { typeof(ProductViewModel), new ProductView() }
            };

            foreach (var item in ItemsSource)
            {
                TabItem tabItem = new TabItem();
                if (views.ContainsKey(item.GetType()))
                {
                    tabItem.Header = item.Header;
                    UserControl view = views[item.GetType()];
                    view.DataContext = item;
                    tabItem.Content = view;
                }
                yield return tabItem;
            }
        }
        #endregion
        public SideMenuControl()
        {
            InitializeComponent();
            MenuItemsTabControl.SizeChanged += 
            	new SizeChangedEventHandler(MenuItemsTabControl_SizeChanged);          
        }
        void MenuItemsTabControl_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            if (ItemsSource == null)
                return;
            Int32 itemCount = ItemsSource.Count();
            if (itemCount >= 2)
            {
                Int32 selectedIndex = MenuItemsTabControl.SelectedIndex;
                MenuItemsTabControl.SelectedIndex = itemCount - 1;
                MenuItemsTabControl.SelectedIndex = selectedIndex;
            }
        }
    } 

In the above code, I have created DepenencyProperty for itemsSource whose type is Collection of IEnumerable.

  • IEnumerable

    .NET Framework provides IEnumerable and IEnumerator interfaces to implement collection like behavior to user defined classes. A developer can implement these interfaces to provide collection like behavior to their classes.

    The IEnumerable interface contains an abstract member function called GetEnumerator() and returns an interface IEnumerator on any success call. This IEnumerator interface will allow us to iterate through any custom collection.

    The IEnumerable<T> interface is a generic interface that provides an abstraction for looping over elements.

    I have written BuildItemsSource method to return collection of viewmodels and its return type is IEnumerable.

I have used the Yield keyword which returns an enumerator object.

  • Yield

    The yield keyword is used in an iterator block to provide a value to the enumerator object or to signal the end of the iteration. When used, the expression is evaluated and returned as a value to the enumerator object.

    The yield keyword signals to the compiler that the method in which it appears is an iterator block. The compiler generates a class to implement the behavior that is expressed in the iterator block. In the iterator block, the yield keyword is used together with the return keyword to provide a value to the enumerator object. This is the value that is returned.

    A yield statement cannot appear in an anonymous method.

I have written a SizeChange Event Handler for MenuItemsTabControl which provides user to maintain selected index of TabItems when user shows/hides sidebar.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Hiren Khirsaria
Software Developer (Senior)
India India
has Total 5+ years of Experience in Microsoft.Net Environment. out of that,
 
2 + year of Excperience in .Net Development with C# and SQL Server 2005/2008.
 
3 + years of Experience in WPF/Silverlight.
 
Current area of Development in Mono for Android (Xamarin), Silverlight/ WPF and Windows Phone 7 Application.
 
Follow him on : http://hirenkhirsaria.blogspot.com/

Comments and Discussions

 
QuestionGood work but how can i make straight forward use of it dynamically (without MVVM) PinmemberMK87_200820-Apr-13 9:46 
AnswerRe: Good work but how can i make straight forward use of it dynamically (without MVVM) PinmemberHiren Khirsaria20-Apr-13 23:05 
GeneralRe: Good work but how can i make straight forward use of it dynamically (without MVVM) PinmemberMK87_200821-Apr-13 5:26 
QuestionGood stuff. PinmemberGokulan Venattu21-Aug-12 20:52 
QuestionScreenshot Pinmemberjeffb4222-Dec-11 6:19 
AnswerRe: Screenshot Pinmemberkapil bhavsar26-Dec-11 18:43 
I don't care to read it without a screenshot.

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web01 | 2.8.140721.1 | Last Updated 23 Dec 2011
Article Copyright 2011 by Hiren Khirsaria
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid