F# – Working classes

Lately I am trying improve my programming by following some Katas. One of the things, I have been trying to learn was Functional Programming. So I decided to spend more time and try to write the same code I write in C# to see how can I adopt and learn faster. So in this blog, we will look at a small program I was trying to do in C#

1. Using third party control:

To use third party control, you do exactly same as you would do in C#, add the reference and then instead of using ‘using namespace’ in F# you would open the namespace to use in the code. In this example I am using bcParser.Net.dll to evaluate arithmetic expression. So the open would look like something like the following

open Bestcode.Mathparser

2. Working with a class:

Now that we added reference to the namespace we need to instantiate the class and add arithmetic expression to it to use it. For our example, our expression is “1+2” and expect the result to 3. To instantiate the class

let mathParser = MathParser()

now that mathParser is the instance of the class, we need assign the expression to mathParser expression member variable. This is done little different than C#. In C# we will do some thing like the following

mathParser.Expression = “1+2”

but in F#, you have to do the following

mathParser.Expression <- “1+2”

3. Printing the result:

Now that we have the expression set, we need to evaluate and print the result to console. This part is very simple

printfn “%s” (mathParser.Value.ToString())

make sure you put the whole thing parenthesis otherwise you will get compiler error.

One thing I noticed while using F#, the compiler errors are so explanatory, you will able to figure out what were you doing wrong in the code.

Advertisements

Component One Silvelright FlexGrid Tip 7 (ChildItemsPath with heterogeneous collection)

In one of my previous blog I have explained how to create tree view inside the grid using ChildItemsPath. There was a limitation at that time (prior to version 206), the child item must be of the same type of parent collection. In another words, both parent and child should be of same type. The best example is Person class. In a person class you can have children, but the children have to of type Person itself. In a way it was kind of limiting. With drop 206, Component One removed the limitation and now you can have children of different type. To show how it is done, lets look at the two classes that I am going to use today.

public class SalesPerson
    {
        public string Name { get; set; }
        public List<Sales> Children { get; set; }
    }
    public class Sales
    {
        public string Name { get; set; }
        public int Quantities { get; set; }
        public int Amount { get; set; }
    }

So we have two classes one is sales person and another one is sales. Each sales person have made number of sales and that I want to display in grid using ChildItemPath. Lets look at the XAML

<c1:C1FlexGrid ItemsSource="{Binding SalesPeople}" ChildItemsPath="Children" AutoGenerateColumns="False">
            <c1:C1FlexGrid.Columns>
                <c1:Column Binding="{Binding Name}"/>
                <c1:Column Binding="{Binding Quantities}"/>
                <c1:Column Binding="{Binding Amount}"/>
            </c1:C1FlexGrid.Columns>
        </c1:C1FlexGrid>

Nothing new here, everything is same as before. In the previous version of FlexGrid, when you run, you will get run time error, but with new drop 206, you will not get any error and the result should be something like

image

There you go, it is as simple as that.

Working with Data Tables in C#

Most of my work I have done, when it comes to do data look up or creating collection, I always used some sort of ICollection. I was able to solve them using Dictionary or List etc., Recently I came across a situation where none of these were able to solve it directly. I was going to create a custom Collection derived off of IDictionary then I came across DataTable (thanks to Bernardo @ Component One). Once I started using in memory DataTable then there is no going back, you get hooked. It is very powerful. With Linq on top of it, you will write code as if you have local SQL table. The funny thing is, it was there all along except since Silverlight did not support DataTable out of the box, you never use it and forgot about it. By the way, even though Silverlight by itself does not support DataTable, Component One does have their implementation of DataTable for Silverlight. So if you need to use Data Table for Silverlight you can look them up.

There are lot of excellent references out there if you haven’t used DataTable at all. Here are some of the references that I used for get me going

http://www.codeproject.com/KB/grid/practicalguidedatagrids2.aspx

http://msdn.microsoft.com/en-us/library/system.data.datatable.aspx

you got the idea, it is there and use it. I am not going to explain how and what since it has been documented multiple times by talented people. I want to add couple things, I did when I start using it.

1. Please make sure you have primary key defined in the data table otherwise when you get to large data table, your search will slow down drastically. I had one table, where my search took more than a minute without primary key, by adding primary key, my select dropped to seconds.

2. When you do query against the table, it returns collection of DataRow, which by default does not support ForEach in linq, so I added a extension method like the following

public static void ForEach<T>(this IEnumerable<T> sequence, Action<T> action)
{
   foreach (T item in sequence) action(item);
}
 

3. You could avoid the extension by converting the DataRow collection to List and then you can use ForEach in the List type, but I would not recommend that approach since, it is creating additional memory.  Most of the times when you use any of the linq comment, you normally use single statement. In case if you want to use more than one statement, you can do something like this

collection.ForEach( item => { method1(); method2(); });

I update this blog post I learn more about DataTables.

Component One Silvelright FlexGrid Tip 6 (Group Header customatization)

Continuing our previous example of using Data Table to create grid on the fly, we will add one more column for grouping purpose to produce an output like the following

image

This also shows how to do grouping when using DataTable in Silverlight. So lets look at the code which generates the data to populate the grid and also grouping.

private void LoadData()
{
   _dataTableWithData = new DataTable();
   _dataTableWithData.Columns.Add("ID");
   _dataTableWithData.Columns.Add("Name");
   _dataTableWithData.Columns.Add("Age");
   _dataTableWithData.Columns.Add("Group");
   for (int i = 0; i < 10; i++)
   {
      int grp = ((i>3)?1:i);
      _dataTableWithData.Rows.Add(i, "Name" + i.ToString(), i, grp);
   }
   var gd = _dataTableWithData.DefaultView.GroupDescriptions;
   gd.Add(new PropertyGroupDescription("Group"));
}

As you can see, we create group row as we would create normal group row in FlexGrid. When we run the code it creates the groups properly but I do not like the default group header information in the group row. It shows

Group: value (number item)

What if I do not want to show the number of item in the parenthesis, how would I go about not showing it? That is what we are going to see today. This is easily achieved by using a custom converter for GroupHeaderConverter. Here is the custom header converter that we need to do to show only ‘Group : GroupName’

public class GroupHeaderConverter:IValueConverter
{
  public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
  {
     var group = value as CollectionViewGroup;
     if (group != null)
        return string.Format("Group: {0}", group.Name);
     return null;
  }

  public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
  {
   throw new NotImplementedException();
  }
}

As you can see it is very simple value converter. For every group, we check and see if the row is a group row and if it is, then just return “Group: ” + group.name. One thing you need to make sure to use, the first type conversion. Make sure you you get the group information of type CollectionViewGroup. With that you get all group related information. Which is very powerful if you want to handle grouping completely different. Now that we have a group header converter, we need to let flex grid know to use this converter for the group headers by

_flex.GroupHeaderConverter = new GroupHeaderConverter();
That's all about it, now if you run the program you get the group header the way we wanted it to be.

image


Not only we saw how to customize the group header, we also saw how to do grouping in Data Table. Thanks Bernardo for the pointers.

Working with DataTable in Silverlight 4

Silverlight 4 out of the box does not support DataTable as its desktop counter part, WPF. But third party controls are here for the rescue. In this blog we will look at, what it take to create a simple grid and use Data Table that we love. As you might have guessed it, I am using Component One controls. Component One provides a namespace C1.Silverlight.Data, which have DataTable implementation that we have been using. So now that we know, we can use Data table, lets create a simple Grid and populate the data.

Create a Silverlight application and add grid control in your XAML as follow;

<Grid x:Name="LayoutRoot" Background="White">
        <c1:C1FlexGrid ItemsSource="{Binding DataTableWithData, Mode=TwoWay}" IsReadOnly="False" AutoGenerateColumns="True" Name="_flex"/>
    </Grid>

Nothing new here, my Flex Grid control bound a property in my view model. Before we go and code, we require following references in our project to run

c1.silvelright.dll

c1.Silvelright.data

System.Windows.Data

System.Windows.Controls.Data

Now lets look at the view model code;

private DataTable _dataTableWithData;

publicDataView DataTableWithData

{

     get

   
{

        if(_dataTableWithData == null)

            LoadData();

        return_dataTableWithData.DefaultView;

     }

}

_dataTableWithData property is our underlying data source. Which is nothing but DataTable, which is Component One data table type. If you notice we are not really binding data table to the grid control rather, we are binding DataView to the grid control. DataView implements the IEnumerable interface thus make it bindable to grid control. If you were like me trying out and not seeing the data in your grid, probabily your property type is incorrect.

Now lets look at the code which loads data to the data table

private void LoadData()
{
     _dataTableWithData = new DataTable();
     _dataTableWithData.Columns.Add("ID");
     _dataTableWithData.Columns.Add("Name");
     _dataTableWithData.Columns.Add("Age");
     for (int i = 0; i < 10; i++)
     {
          _dataTableWithData.Rows.Add(i.ToString(), "Name" + i.ToString(), i);
     }
}

There is nothing special here, creating and populating the data table as you would do in any other format. Now lets run and see the result;

image

 

That’s about it. To summarize

1. Make sure you use the references I mentioned above in your project.

2. Use Data Table as local variable to hold data but do not bind control to that property.

3. Use DataView type for binding it to the grid.

4. To bind data table to grid, you return ‘DefaultView’ of the data table.

Component One Silverlight FlexGrid Tip 5 (Group Summary Row positioning)

Continuing on from the previous tip on grouping, we go one step further. When we generate the grouping, Component One provides couple of options to how to render them. Well there are 3 to be precise. Component One have a property called ‘GroupRowPosition’. Which lets the developer to position the group row on top of the group or below the group or don’t show the group altogether.

1. GroupRowPosition=’AboveData’

<c1:C1FlexGrid Name="flexGrid" ItemsSource="{Binding PeopleCollection}" AutoGenerateColumns="False" GroupRowPosition="AboveData" >

As the name suggests, on UI rendering, C1 will place the group summary information above the data as shown below

image

If you do not provide this option in the grid, this is the default behavior.

2. GroupRowPosition=’BelowData’

<c1:C1FlexGrid Name="flexGrid" ItemsSource="{Binding PeopleCollection}" AutoGenerateColumns="False" GroupRowPosition="BelowData" >

This forces the summary row to show at the bottom of the group row. This is similar to Excel, when you group, you have an option to render the summary row at the bottom.

image

3. GroupRowPosition=’None’

<c1:C1FlexGrid Name="flexGrid" ItemsSource="{Binding PeopleCollection}" AutoGenerateColumns="False" GroupRowPosition="None" >

Not sure why you would do that but it is available. With this option the group row is removed but the grouping is still in place.

image

If you are requirements needs lots of grouping and want to create grouping and look and feel like Excel, please have a loot at C1FlexGridExcel control which is derived off of C1FlexGrid control. Which by fault look like Excel.