Sep 21 2009

Telerik Sales Dashboard - Abide by Prism!

Category: Prism 2.0 | silverlight 2.0 | Telerik ControlsBil@l @ 22:32
There is no doubt that once you finish reading the Prism 2.0 (Composite Application Library) and try out all of the quick starts that accompany the guidance; it is a must to check out the Telerik Sales Dashboard. (http://demos.telerik.com/silverlight/salesdashboard)

Telerik not only pioneering in control development that targets the Microsoft .Net framework but also in educating developers all around the world with their extra efforts of:

  1. Code library
  2. Free software
  3. Extensive documentation
  4. Flash-Quick customer support
  5. Telerik labs
  6. Free Open-source projects

 

One of those major educating applications that Telerik delivers is the Telerik Sales Dashboard. It has been built on top of WPF and Silverlight keeping in mind the MVVM design pattern (Model-View-ViewModel) and Prism (Modularity, UI composition, global events, commanding, etc …)

You can download the source code to check it out and learn from it here (link)

In the whitepaper that accompanies in the Dashboard, I read the following:

PeriodSelector Module

This module handles the task of displaying a RadCalendar in a popup that can be used to select a range of dates for filtering data displayed in other modules. To close the popup containing the RadCalendar control when the user clicks outside of it, we subscribe to the MouseLeftButtonUp event of the RootVisual element of the application. We do not use the MouseLeftButtonDown event because it is used and handled internally by most controls and thus it is inappropriate for our purpose.

Also, we need to bind several properties of UI elements in this module to properties defined in the code-behind of the view, which are then in turn bound to properties in the viewmodel. This code-behind binding is necessary because the project requirements are not achievable with the XAML bindings available in Silverlight. This is a deviation from the Prism guidance, but, as already established, patterns should not be followed blindly if they block application requirements.

I found some code in the PeriodSelectorView.xaml.cs file that shouldn’t be present in a typical Prism application however, as it has been established in the Dashboard’s whitepaper, we shouldn’t follow a design pattern blindly if it blocks our work.

However, the code behind that was present could be replaced by implementing a new CommandBehavior that targets the RadCalendar. That was the first part of moving the code from code-behind into the PeriodSelectorViewModel.cs file. The other part is hooking up to the System.Windows.Application.Current.RootVisual.MouseLeftButtonUp  event inside the ViewModel file itself. The second part is easy and straight forward, so I will focus on the first one.


using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Data;
using System.Collections;

namespace Telerik.SalesDashboard.PeriodSelector
{
public partial class PeriodSelectorView : UserControl
{
public PeriodSelectorView(PeriodSelectorViewModel viewModel)
{
InitializeComponent();
this.DataContext = viewModel;

Binding b = new Binding();
b.Mode = BindingMode.TwoWay;
b.Path = new PropertyPath("CalendarSelectedDates");
this.SetBinding(PeriodSelectorView.SelectedDatesProperty, b);
calendar.SelectionChanged += (s, e) => this.SelectedDates = calendar.SelectedDates.ToList();
}

public IList SelectedDates
{
get
{
return (IList)this.GetValue(SelectedDatesProperty);
}
set
{
this.SetValue(SelectedDatesProperty, value);
}
}

// Using a DependencyProperty as the backing store for SelectedDates. This enables animation, styling, binding, etc...
public static readonly DependencyProperty SelectedDatesProperty =
DependencyProperty.Register("SelectedDates", typeof(IList), typeof(PeriodSelectorView), null);
}
}

What has been done above is:

  1. Define SelectedDates as a Dependency property on the View itself
  2. Define CalendarSelectedDates as a property on the ViewModel class
  3. Define a Binding between the above two properties
  4. Hooking up to the SelectionChanged event of the RadCalendar to fill the SelectedDates property hence filling the CalendarSelectedDates property.

 

The above was a way to hook into RadCalendar control on the View to retrieve selected dates and pass back the value to the ViewModel.

Now, what I did was:

     1. Removing all code-behind from the View

     2. Define a new DelegateCommand as follows:     

public ICommand CalendarSelectedCommand { get; private set; }
      3.  Instantiate the DelegateCommand as follows:
        this.CalendarSelectedCommand = new DelegateCommand<IList>(OnCalendarSelectionChanged);
private void OnCalendarSelectionChanged(IList args)
{
this.CalendarSelectedDates = args;
}

             4. Implemented a new RadCalendarCommandBehavior class.  As you know in Prism the CommandBevaior class does many things among which are:

a. Adds Commanding behavior into a Control

b. Defines the Command, CommandParameter and CommandBehavior attached properties that can be hooked to a Control.

c. Plays the role of proxy between Command definition and Control that the command is defined on where it attaches to a specific event of a Control and defines the event handler for that event, so that when the event is fired, the command is being called and executed.

Now, firing the event of a Control causes the attached event handler defined inside the CommandBehavior to fire. Usually this event handler calls the Execute method of the CommandBehavior that internally delegates the call to the Execute method on the Command it defines as a Dependency property.

Thus you can see how important the CommandBehavior class in attaching a Command behavior into a Control.

The Prism ships with the ClickCommandBehavior class only. When I saw the code written inside PeriodSelectorView.xaml.cs I realized that all what I need is create a RadCalendarCommandBehavior.cs class that attaches a new Command into the RadCalendar class by hooking into the RadCalendar.SelectionChanged event.

The purpose is to fire a command on the RadCalendar that can be handled inside the PeriodSelectorViewModel.cs class where I can easily retrieve the selected dates and hence no need for the mediator SelectedDates dependency property inside the View and no need for accessing the RadCalendar.SelectionChanged event. The goal is the same however, the “how” is the different and I believe using commands is more elegant!

I will not go into the details of creating the RadCalendarCommandBehavior class, the code is straight forward based on Prism knowledge


using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Practices.Composite.Presentation.Commands;
using Telerik.Windows.Input;
using Telerik.Windows.Controls;
using System.Linq;
using System.Collections;

namespace Telerik.SalesDashboard.PeriodSelector
{
public class RadCalendarCommandBehavior : CommandBehaviorBase<RadCalendar>
{
public RadCalendarCommandBehavior(RadCalendar source)
: base(source)
{
source.SelectionChanged += new Telerik.Windows.Controls.SelectionChangedEventHandler(source_SelectionChanged);
}

void source_SelectionChanged(object sender, Telerik.Windows.Controls.SelectionChangedEventArgs e)
{
var calendar = sender as RadCalendar;
if (calendar != null)
{
this.Command.Execute(calendar.SelectedDates.ToList());
}
}
}

public static class SelectionChanged
{
private static readonly DependencyProperty SelectionChangedCommandBehaviorProperty = DependencyProperty.RegisterAttached(
"SelectionChangedCommandBehavior",
typeof(RadCalendarCommandBehavior),
typeof(SelectionChanged),
null);

public static readonly DependencyProperty CommandProperty = DependencyProperty.RegisterAttached(
"Command",
typeof(ICommand),
typeof(SelectionChanged),
new PropertyMetadata(OnSetCommandCallback));

public static readonly DependencyProperty CommandParameterProperty = DependencyProperty.RegisterAttached(
"CommandParameter",
typeof(object),
typeof(SelectionChanged),
new PropertyMetadata(OnSetCommandParameterCallback));


public static void SetCommand(RadCalendar calendar, ICommand command)
{
calendar.SetValue(CommandProperty, command);
}

public static ICommand GetCommand(RadCalendar calendar)
{
return calendar.GetValue(CommandProperty) as ICommand;
}

public static void SetCommandParameter(RadCalendar calendar, object parameter)
{
calendar.SetValue(CommandParameterProperty, parameter);
}

public static object GetCommandParameter(RadCalendar calendar)
{
return calendar.GetValue(CommandParameterProperty);
}

private static void OnSetCommandCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
{
RadCalendar calendar = dependencyObject as RadCalendar;
if (calendar != null)
{
RadCalendarCommandBehavior behavior = GetOrCreateBehavior(calendar);
behavior.Command = e.NewValue as ICommand;
}
}

private static void OnSetCommandParameterCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
{
RadCalendar calendar = dependencyObject as RadCalendar;
if (calendar != null)
{
RadCalendarCommandBehavior behavior = GetOrCreateBehavior(calendar);
behavior.CommandParameter = e.NewValue;
}
}

private static RadCalendarCommandBehavior GetOrCreateBehavior(RadCalendar calendar)
{
RadCalendarCommandBehavior behavior = calendar.GetValue(SelectionChangedCommandBehaviorProperty) as RadCalendarCommandBehavior;
if (behavior == null)
{
behavior = new RadCalendarCommandBehavior(calendar);
calendar.SetValue(SelectionChangedCommandBehaviorProperty, behavior);
}

return behavior;
}
}
}

5. What is left is to add the following into the PeriodSelectorView.xaml:

a.       Add a new XML namespace reference into the header of the UserControl:

xmlns:MyCommands="clr-namespace:Telerik.SalesDashboard.PeriodSelector"
  <telerikInput:RadCalendar …  MyCommands:SelectionChanged.Command="{Binding CalendarSelectedCommand}"   … />

That’s all what you need to do to remove the code-behind from the PeriodSelectorView into the PeriodSelectorViewModel !

 

If you find that the above can be improved, or anything you find you couldn’t understand, or you think is not suitable, etc … Please don’t hesitate to contact me at: bhaidar @ gmail.com

Regards

 

Tags: , ,

Aug 26 2009

Anonymous Types in Silverlight 2.0

Category: silverlight 2.0Bil@l @ 17:03

If you are querying a collection in Silverlight 2.0 using LINQ and you want to extract a subset of the properties on the queries collection objects, you cannot make use of Anonymous Types in LINQ. For instance the following query won't return any value:

    public class Employee
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }

            List<Employee> employees = new List<Employee>();
            employees.Add(new Employee { FirstName = "Bilal", LastName = "Haidar" });
            employees.Add(new Employee { FirstName = "Bill", LastName = "Gates" });

            var results = from emp in employees
                          select new { FirstName = emp.FirstName };

results will be empty as Anonymous Types are not supported.

A solution can be done by disecting your domain objects in this case a very simple object (Employee) into smaller structs

    public struct SubEmployee
    {
        public string FirstName { get; set; }
    }

And the query could be as follows:

            IEnumerable<SubEmployee> results = from emp in employees
                          select new SubEmployee{ FirstName = emp.FirstName };

 

You can have as many structs as you want to ease your work.

Hope this tip helps!
Regards

Tags:

Jun 23 2009

Columns &amp; Rows: Part II Silverlight 2.0 DataGrid Columns

Category: silverlight 2.0Bil@l @ 07:21

Here is the second installment of my series Columns and Rows on the ASPNETPRO magazine.

Columns & Rows: Part II  Silverlight 2.0 DataGrid Columns

If you haven't yet read the first installment, you can read the blog post here: Columns & Rows Part I: Silverlight 2.0 DataGrid Properties.

 

Hope you enjoy it!
Regards

 

Tags:

Jun 23 2009

Part I - Silverlight 2.0 DataGrid Properties

Category: silverlight 2.0Bil@l @ 06:49
I would like to invite you to read the first installment of the Columns & Rows series on the Silverlight 2.0 DataGrid that is being published by ASPNETPRO magazine. Columns & Rows Part I: Silverlight 2.0 DataGrid Properties

Article Introduction
This article is the first in a series that will tackle most of the features of the Silverlight 2.0 DataGrid. There are several sections to discuss and explain regarding the Silverlight 2.0 DataGrid, including an overview of the DataGrid properties, auto-generating columns, defining columns in XAML, defining columns at runtime, implementing master/detail features, paging and sorting, and editing/deleting/adding rows using the DataGrid.

Through the course of this article, you’ll get an overview of the majority of the DataGrid properties that play an important role in configuring the DataGrid, like setting the column width and row color, and alternating colors, among other things.

Hope you enjoy and benefit from reading it.
Regards

Tags:

Jun 5 2009

Columns &amp; Rows: Part I Silverlight 2.0 DataGrid Properties

Category: articles | aspnetpro | silverlight 2.0Bil@l @ 19:36

I invite you to read my latest article on ASPNETPRO magazine:

Columns & Rows: Part I Silverlight 2.0 DataGrid Properties

This is the first in a series of few articles to cover all features of the Silverlight 2.0 DataGrid.

 

Enjoy it!
Regards

 

Tags: , ,

May 30 2009

Telerik Sales Dashboard Demo for Silverlight and WPF

Category: silverlight 2.0 | Telerik Controls | WPFBil@l @ 20:52

Telerik just release the Telerik Sales Dashboard Demo for both Silverlight and WPF.

Check this blog post for more info on the Dashboard: Telerik Dashboard for Silverlight and WPF

 

Hope you enjoy it!
regards

Tags: , ,

May 18 2009

XAML Power Toys for WPF and Silverlight 2.0 - V4.0

Category: silverlight 2.0 | XAML Power Toys V4.0Bil@l @ 14:22

A very nice Visual Studio 2008 SP1 Add-in that you can find handy when developing with Silverlight 2.0 is the XAML Power Toys for WPF and Silverlight.

You can create a XAML business form by using a simple form that drives you step by step in selecting in creating your rows and columns.

You can also create a XAML business form based on a domain object in your project, and much more features.

 

If you are developing in Silverlight 2.0, it is a must to check this Add-in. XAML Power Toys for WPF and Silverlight 2.0 V 4.0

Hope this helps,
Regards

Tags: ,

May 2 2009

Internal Access Modifier on C# Namespaces

Category: C# | silverlight 2.0Bil@l @ 00:08

As part of a Silverlight applicatin I am currently developing, I have a small API that ships with the application that allows extending it with more features. I had few "Default" implementations inside the API and hence I placed them within a Namespace where all classes are marked as Internal.

Now, when I started working on the app, I created a Visual Studio Blank Solution. So the Silverlight application and the API are in the same blank empty solution inside VS 2008. When I access the main Namespace of the API, I always get to see the name of the default implementations, however as empty since all classes inside it are internal. 

So how can I hide the Namespace that contains all those implementations? I read this blog here "http://www.bartlannoeye.be/blog/2008/08/06/MakeCNamespaceInternal.aspx" which helped me do what I want, but I thought of illustrating a bit more here in this post to clarify the idea more.

Rule 1: Make sure all the classes inside the Namespace you want to hide are marked as Internal.

Rule 2: If you add a reference to a project whose source code is in the same solution, you will always see the Namespace name however empty with no classes.

Rule 3: If you add a reference to a project whose source code is not present in the current application, the Namespace name that contains all internal classes will be hidden.

 

I tried it out and seems to work very nice.

Hope this helps,
Regards

Tags: ,

Apr 15 2009

Silverlight Release History : Q1 2009 SP1 (version 2009.1.413)

Category: silverlight 2.0 | Telerik ControlsBil@l @ 09:20

Q1 2009 SP1 (version 2009.1.413)

 

 

SilverlightGridView Icon

RadGridView for Silverlight

New Features:

  • CanUserSortColumns property added
  • Disabled CheckBox for boolean column in view mode instead True/False added
  • Cells property added for grid rows - Items is now obsolete.
  • ExcelML export added
  • Exporting improvements (styles & formatting)
  • Exporting event added
  • Support for mouse over state in Cells added
  • GridViewComboboxColumn added
  • DistinctValues IValueConverter support added
  • RowAppearance settings moved to GridViewDataControl (RowStyle, HeaderRowStyle, etc.) - RowAppearance is now obsolete
  • HeaderRowStyle property added for GridViewDataControl
  • GroupRowStyle property added for GridViewDataControl
  • NewRowStyle property added for GridViewDataControl
  • Added Validation style for Vista, Summer and Office_Black themes
  • TAB naviagation improvements
  • CellTemplate and CellEditTemplate DataTemplate properties for GridViewColumn added
  • CreateCellElement and CreateCellEditElement virtual methods for GridViewColumn added

Fixes:

  • Export does not take into account columns that are hidden is now fixed
  • Height cannot be set in XAML for the grid rows is now fixed
  • Duplicate rows in Export to Excel is now fixed
  • HeaderText cannot be set in runtime is now fixed
  • GridViewColumn IsVisible now will not reset GridViewDataControl template
  • Cells are not created if the grid is not visible
    Control+Click multiple selection broken after switching tabs in a TabControl is now fixed
  • Column reordering with custom filter description added to the composite filter description of the grid is now fixed
  • DataElement property of RowLoadedEventArgs throws exception on new row is now fixed
  • Async binding does not work properly with filtering
  • Sorting on nested or indexed properties is now fixed
  • Distinct values on ntext columns exception is now fixed
  • Sorting on ntext columns is now fixed
  • CustomTypeDescriptor problems with sorting and distinct values are now fixed (WPF only)
  • Filtering on string when target value is null is now fixed
  • GroupingRequested not raised on group panel cell close button click is now fixed
  • DataFormatString does not work properly on export is now fixed
  • Vertical scrollbar margin not calculated properly when new row is visible is now fixed
Silverlight RadChart Icon

RadChart

New Features:

  • Added two new 2D chart types: StackedLine and StackedSpline
  • Added AxisY.ExtendDirection property. This property will define if and in which direction AxisY will automatically add an additional step in order to ensure there is always a gap between the graph and the chart area top/bottom end. It is respected only when AutoRange property is set to true and IsZeroBasedProperty is treated with higher priority. The possible values are:

    • AxisExtendDirection.None - the Y axis will not be extended
    • AxisExtendDirection.Down - the Y axis will have an additional item at the bottom
    • AxisExtendDirection.Up - the Y axis will have an additional item at the top
    • AxisExtendDirection.Both - the Y axis will have an additional item at both - top and bottom
    • AxisExtendDirection.Smart - acts like AxisExtendDirection.Both with a single difference: the axis will never be extended outside the 0 value
  • New series types - StackedLine and StackedSpline
  • Exposed Style properties for customization of the visual elements of RadChart:

    • RadChart.TitleStyle - gets or sets the title style
    • RadChart.LegendStyle - gets or sets the legend style
    • SeriesDefinition.PointMarkItemStyle - gets or sets the Style associated with each point mark (where applicable)
    • SeriesDefinition.SeriesItemLabelStyle - gets or sets the series item label style
    • ChartArea.AxisXStyle - gets or sets the axis X style
    • ChartArea.AxisYStyle - gets or sets the axis Y style
    • ChartLegend.LegendItemStyle - gets or sets the legend item style
  • PointMarks shape and appearance can now be customized through
  • SeriesDefinition.Appearance.PointMark complex property
  • Added item tooltip format
  • Introduced automatic AxisX.LayoutMode selection that takes the actual displayed chart series into account

Changes:

  • Fixed an issue with series item format not working for the last item
  • Applying styles to AxisXLabel2D is now possible
  • Fixed an issue with wrong ItemIndex in ChartItemClickEventArgs for radial series.

Breaking Changes:

  • AxisY.AutoScale is now obsolete. Please, use AutoRange property instead
  • Numeric label formats have changed - there is no {0} placeholder used anymore. For example the old format "{0:C}" is now written as "C"

RadGauge

New Features:

  • Semi-circle styles for radial gauges
  • Quadrant-like styles for radial gauges
Silverlight RadEditor Icon

RadEditor

Fixes in Firefox:

  • Telerik.Windows.Controls.Editor.dll – fixed mistaken assembly info affecting IntelliSense
SilverlightMaskedTextBox Icon

RadMaskedTextBox

  • SelectionStart, SelectionLength, AutoCompleteInterval - new properties added
RadPanelBar

RadPanelBar

  • Accordion functionality
RadDragAndDropManager Icon

RadDragAndDropManager

  • Drag-Related properties can now be set in the constructor of the RootVisual, no Null Exceptions will occur
  • When the drag Source is set as a DragCue, it is correctly put back in the visual tree on drop complete
  • Drag-drop across multiple nested windows now works as expected
RadTabControl Icon

RadTabControl

  • TemplateBinding to HeaderTemplate now added in all templates
RadWindow Icon

RadWindow

  • Modal Window background now visible in Alert, Prompt, Confirm.
RadMediaPlayer Icon

RadMediaPlayer

Fixes:

  • Fixed RadMediaPlayer bug affecting the CurrentItem property when set before the template has been applied
  • Removed a Loaded Trigger which confused Blend during template editing

Memory Leak Fixes:

  • RadWindow, RadTreeView, RadMenu, RadNumericUpDown, RadSlider

Tags: ,

Apr 14 2009

Microsoft Silverlight Installation Experience White Paper and Sample Code

Category: silverlight 2.0Bil@l @ 00:31

Silverlight team released the Microsoft Silverlight Installation Experience White Paper and Sample code.

You can grab this White Paper + Sample code by following this URL (Here)

 

Hope you like and enjoy the new resource!

Regards

Tags: