IValueConverter for Binding in WinForms

I’m currently working on a Winforms project and there was a need if a product is in stock, the background of the ‘details product panel’ should be green, otherwise it should be red.
In xaml related technologies, this is an easy job. You bind the IsInStock (boolean) property on the BackColor property of the panel and create a converter which inherits from IValueConverter (InStockToColorConverter) which converts the boolean property to the correct color.

In Winforms you can create (in code) a binding too, but you can’t specify a converter to convert a boolean (IsInStock property) to a color. Todo that you should write a lot of code in your SelectionChanged event…
For easly tackle this job, I have written a CustomBinding class where you can specifiy a converter which implements the IValueConverter inferface, then you can do the job with one line of code:

DetailsPanel.DataBindings.Add(new CustomBinding("BackColor", ProductsBindingSource, "IsInStock",new InStockToColorConverter()));

You can download an example project and the full source here.

What the (near) future will bring: Summary (TechDays 2012)

Last week, I went to the main conference of TechDays (14 & 15 february) Belgium, Microsoft’s yearly event for IT professionals and developers.
Because I am a developer, I went to the developer track sessions.

TechDays 2012

I tried to wrote down a summary of some interesting sessions which I followed.

First of all, there was the keynote of Scott Gurie, his keynote was focusing on all items about Windows Azure. Briefly he explained what is Windows Azure, what can you do with Windows Azure and for what can you use Windows Azure. A recording of the keynote is already available on Channel 9.

There were many sessions about Windows 8 and developing Metro applications for Windows 8. For building these applications you can use your existing Silverlight or WPF skills (XAML + C#) or HTML (+ CSS) and JavaScript skills.

I went also to a session of Windows Phone 7.5: it was a session about advanced concepts for coding a WP7 app. Ben Riga said that Windows Phone 8 wouldn’t come soon (in the near future), but more details he couldn’t say…

There was also a very interesting session of Bart De Smet (The Future of C# and Visual Basic). In this session he showed a lot of code examples of C# 5.
You can summarize this session with one important sentence: C# 5 is focused on async programming, introducing a few new keywords in C# 5 for easily async programming like async, await,…
Here a small example:

public async Task<int> ExampleMethodAsync()
{
    // . . .

    // At the await expression, execution in this method is suspended and,
    // if AwaitedProcessAsync has not already finished, control returns
    // to the caller of ExampleMethodAsync.
    int exampleInt = await AwaitedProcessAsync();

    // . . .

    // The return statement completes the task. Any method that is
    // awaiting ExampleMethodAsync can now get the integer result.
    return exampleInt;
}

More examples, tutorials, downloads can you find on MSDN.

There were also sessions about Silverlight 5 from one of my college Kevin Dockx. He explained how you can set up an good architecture for building Silverlight applications in combination with RIA services. Also a session of  Gill Cleeren who has covered some advanced topics in Silverlight such as duplex bindings, sockets, MEF,…
Laurant Bugnion demonstrated the new features of his new version of MVVM Light framework which can also be used to build Windows 8 Metro applications.

TechDays 2012 was very interesting and instructive; hopefully I will be back  next year!

Is Silverlight dead (or still alive)?

Is Silverlight dead or still alive, that’s the question of some developers, companies, project managers,… today.

Since Microsoft announced that Silverlight 5 is the last version of Silverlight there are many speculations that everyting is going to html 5…

In my opinion (at this moment :)), I don’t think that html 5 is an alternative for Silverlight 5…
Some of my arguments:

  • At this time html 5 is NOT cross browser, some features works in IE and some others in FireFox an so on, Silverlight 5 runtime is supported on IE, FireFox, Safari and Chrome (not officialy Opera).
  • I saw on TechDays 2012 that Microsoft uses Silverlight for his own products, some examples: Azure Management Console and Microsoft Intune.
  • Microsoft supports Silverlight 5 till 10/12/2021 (see here).
Last but not least, on Windows 8, you can build Metro applications, you can use your existing Silverlight skills (XAML + C#) for building these applications because the XAML for building the UI is the same (syntax, default controls,…) as in Silverlight applications.
For the HTML/CSS/JavaScript developers there is also support for this languages in Windows 8 for building Metro applications. For more information about building Metro applications, I suggest to look on the official Microsoft website, you can find there a lot of tutorials and example code.

Another interesting read of ‘The Future Of Silverlight’.

Do you have an other opinion (or the same :)) about the future of Silveright, feel free to write it down in a comment on this blog post!

Create a DataGridToolTipTextColumn for the Silverlight DataGrid

Last I have created a DataGrid column which views a tooltip when you hover over the content (text) of the column. These can be usefull when you have many columns within long textdata.
For the tooltip I have used the ‘Silverlight Advanced ToolTips’ library of Xavier De Coster which you can find on CodePlex.

Create a new class in your project and paste the following code:

public class DataGridToolTipTextColumn : DataGridTextColumn
    {
        protected override FrameworkElement GenerateElement(DataGridCell cell,
                                                            object dataItem)
        {
            TextBlock textBlock = new TextBlock();
            textBlock.SetBinding(TextBlock.TextProperty, this.Binding);
            textBlock.Margin = new Thickness(0, 3, 0, 3); ;
            textBlock.VerticalAlignment = VerticalAlignment.Center;
            Silverlight.Controls.ToolTips.ToolTip toolTip =
                            new Silverlight.Controls.ToolTips.ToolTip();
            toolTip.InitialDelay = 2;
            toolTip.DisplayTime = new Duration(new TimeSpan(0, 0, 5));
            TextBlock textBlockForTt = new TextBlock();
            textBlockForTt.SetBinding(TextBlock.TextProperty, this.Binding);
            toolTip.Content = textBlockForTt;
            toolTip.Language = XmlLanguage.GetLanguage(Thread.CurrentThread.
                                                      CurrentUICulture.Name);
            Silverlight.Controls.ToolTips.ToolTipService.SetToolTip(textBlock,
                                                                    toolTip);

            cell.Content = textBlock;

            return textBlock;
        }

    }

Add the namespace to XAML where the class is in and in the DataGrid control you can use the DataGridToolTipTextColumn with the following code:

 
<Controls:DataGridToolTipTextColumn Width="*"
                                    Header="Order"
                                    IsReadOnly="True"
                                    Binding="{Binding Ordername}" />

Extending OrderBy Linq extensions (Synchronous DataGrid Part 2)

A few weeks ago, I have post an article over my Synchronous DataGrid which I have created. The problem was sorting the data ‘synchronously’ of the first DataGrid with the second DataGrid. The default order mechanism of the DataGrid didn’t work correctly anymore. If you will click on a header on the first DataGrid, he sort his data but the data of the second DataGrid isn’t sorted.
The solution for this problem can be are: fire an event if the user click on a header and sort the collection by the property binded on the matching column.
But… the header hasn’t default an OnClick event… Ok, let’s implement it in the Synchronous DataGrid:
I override the OnMouseLeftButtonDown methode, I check if the mouse position on a header of the DataGrid, if yes, get the name of the property wich is binded on the column and fire a new event: DataGridHeaderClickend.

        protected override void OnMouseLeftButtonDown(
             System.Windows.Input.MouseButtonEventArgs e)
        {
            Point pt = e.GetPosition(null);
            var lst = VisualTreeHelper.FindElementsInHostCoordinates(pt, 
                                                                    this);
            var lstHeader = new List<DataGridColumnHeader>();
            foreach (var element in lst)
            {
                if (element.GetType().Equals(typeof(DataGridColumnHeader)))
                    lstHeader.Add((DataGridColumnHeader)element);
            }

            if (lstHeader.Count == 1)
            {
                foreach (var item in this.Columns)
                {
                    if (item.Header.Equals(lstHeader[0].Content))
                        OnDataGridHeaderClickend(new 
                          DataGridHeaderClickedEventArgs(lstHeader[0], 
                                                 GetBindingName(item)));
                }
            }

            base.OnMouseLeftButtonDown(e);
        }

So far so good… Now, we knows on wich column is clicked and we knows what the name of the binded property is of the column.
But… There’s is no Linq OrderBy method which have a paramater of type ‘string’.
The solution is extending the OrderBy and OrderByDescending Linq methods.
You can get the property which some reflection:

 var mem = typeof(T).GetMember(memberName).Single();

            var memType = (mem is System.Reflection.FieldInfo)
               ? ((System.Reflection.FieldInfo)mem).FieldType
               : ((System.Reflection.PropertyInfo)mem).PropertyType;

and build on this manner the regular expression for sorting your collection:

  private static Func<TSource, TKey> CreateKeySelector<TSource, TKey>
        (MemberInfo member)
        {
            Func<TSource, object> getMemberValue = c => (member is FieldInfo)
                    ? ((FieldInfo)member).GetValue(c)
                    : (member is PropertyInfo)
                        ? ((PropertyInfo)member).GetValue(c, null)
                        : null;

            if (getMemberValue == null)
                throw new NotSupportedException
                    ("Only property or field members are supported.");

            Func<TSource, TKey> ret = c => (TKey)getMemberValue(c);

            return ret;
        }

The OrderBy extention method looks like this:

  public static IOrderedEnumerable<T> OrderBy<T>(this IEnumerable<T> source,
                                                 string memberName)
        {
            var mem = typeof(T).GetMember(memberName).Single();

            var memType = (mem is FieldInfo)
               ? ((FieldInfo)mem).FieldType
               : ((PropertyInfo)mem).PropertyType;

            var keySelector = typeof(Extensions)
                .GetMethod("CreateKeySelector", BindingFlags.Static | 
                                               BindingFlags.NonPublic)
                .MakeGenericMethod(typeof(T), memType).Invoke(null,
                                               new object[] { mem });

            var orderByMeth = typeof(Enumerable).GetMethods()
                .Where(c => c.Name == "OrderBy")
                .Where(c => c.GetParameters().Count() == 2)
                .Single()
                .MakeGenericMethod(typeof(T), memType);

            return orderByMeth.Invoke(null, 
                  new object[] { source, keySelector }) 
                              as IOrderedEnumerable<T>;
        }

NOTE: this way of working is not very performant (client-side sorting & reflection), use it only if there is not another way to sort.

You can download a sample application here.

Two-Way binding Autogenerated columns in Silverlight DataGrid

A colleague ask me why his property didn’t update while he was clicking on a checkbox in a column of a DataGrid.
He has set the ItemsSource of his DataGrid to an ObservableCollection of objects with the INotifyPropertyChanged inferface implemented and the setters fires the PropertyChanged event.
The problem is the default value of the ‘binding mode’ of a column (also any binding in Silverlight) is ‘OneWay’, this will means that the property is read only.
You can’t specify the ‘binding mode’ in XAML because there is no XAML for the bindings of the colums with autogenerated columns.

For this problem there is an easy workaround: add the ‘AutoGeneratingColumn’ event to your DataGrid and add the following code in the code behind file:

 private void dataGrid1_AutoGeneratingColumn(object sender, 
_DataGridAutoGeneratingColumnEventArgs e)
        {
           if(e.Column.GetType() == typeof(DataGridCheckBoxColumn))
           {
               DataGridCheckBoxColumn dgc = (DataGridCheckBoxColumn)e.Column;
               dgc.Binding.Mode = BindingMode.TwoWay;
           }
        }

You can do the same for a DataGridTextColumn by changing the if structure:

 if(e.Column.GetType() == typeof(DataGridTextColumn))
           {
               DataGridTextColumn dgc = (DataGridTextColumn)e.Column;
               dgc.Binding.Mode = BindingMode.TwoWay;
           }

You can download my demo code on this link.

Synchronous scrolling DataGrid in Silverlight

If you read the title of this post, you can think WTF. But I have used it in a project… I have used it for hiding some columns in a DataGrid with an expander:

Columns ExpandedColumns not Expanded

You can see in the first image that the first datagrid is expanded and on the second image the first datagrid is not expanded. If you scroll with the first DataGrid the second DataGrid scrolls automatically to the same position of the first DataGrid and vice versa.

You can do this with the following XAML code:

The steps you have to do:

1) Bind the DataGrid wich must scroll synchronous to the current Datagrid on the ‘SynchronousScrollingDataGrid’ property: SynchronousScrollingDataGrid=”{Binding ElementName=firstDataGrid}”
2) Give the ‘RowHeight’ property a hardcoded value, because the back-code of the Synchronous scrolling DataGrid uses this property. If the RowHeight is not set the value is ‘NaN’.
3) As you can see in the example code above you can bind the ‘SynchronousScrollingDataGrid’ property of the second DataGrid to the first DataGrid.

Download sample code

I want to say thanx to my colleague Sandrino Di Mattia for his blog post “Controlling and viewing the ScrollBar positions of your Silverlight DataGrid”. This post was very usefull for me to create my synchronous DataGrid.

Follow

Get every new post delivered to your Inbox.