Silverlight DataGrid – Issues solved!!

Today is a happy day….  

I am actually battling with a Silverlight business application with some interesting design & behavior – in fact it is a migration from a VB6.0 App.. but the design of the screens is not bad and it’s pretty useful to the task they are designed for. 

One of the most costly things I’ve suffered is that I had to show off some information grouped and totalized (nothing strange here, you just have to search a bit and you know the how-to) and also each group of information could have different format on the same column…. and oh my, this has been a real killer… 

I tried to change it programmatically but the Binding is bound to the column… so I tried to change the binding, first through the StringFormat but… hey! it is not bindable! Bummer… then I tried to use a custom Converter and bind the ConverterParameter but it also happened not to be bindable – or I did not find how to implement it. I tried also to implement a custom Converter deriving from FrameworkElement and IConverter so I could create a bindable property for using it instead of the ConverterParameter…. but that didn’t work out properly… 

Until I found a gem, the “Silverlight MultiBinding” solution that a smart guy, Colin Eberhardt conceived & developed to implement a similar binding model to that of WPF, with more funcitons and to be clear, more mature. Silverlight team, we need that on SL ASAP if we are to build serious SL business apps… if not some developers can get near to crazy to solve some “customer needs”… like I have ;). 

Regarding the MultiBinding, you can read from Colin on his blog here: http://www.scottlogic.co.uk/blog/colin/2010/08/silverlight-multibinding-updated-adding-support-for-elementname-and-twoway-binding/ 

Gladly I’m not alone as “Full Databinding Support” is the top requested feature on the Silverlight Feature Suggestions forum here:  http://dotnet.uservoice.com/forums/4325-silverlight-feature-suggestions, with over three thousand points, it’s the Nº1!!. 

Wich includes requests for fabulous features like: 

+ ValueConverter ConvertParameter binding.
+ StringFormat binding.
+ Strongly typed DataBinding support (intellisense).
+ Conditional Binding.
+ Binding to dynamic objects .
+ More extensibility.
+ Etc.. 

Regarding to my solution I implemented it on the DataGridTemplateColumn for each column I needed to format conditionally, considering also that some columns will need to be editable, so I had to use the usual binding for the editable template even that the TwoWay binding works on the Multibinding implementation but I found no way to keep the format from being reset (by now the TwoWay multibinding requires that all the properties are TwoWay). You can see the XAML code next: 

<data:DataGridTemplateColumn Header=”Budget” > 

<data:DataGridTemplateColumn.CellTemplate>

<DataTemplate>

<TextBlock TextAlignment=”Right” > 

<multibinding:BindingUtil.MultiBindings>

<multibinding:MultiBindings>

<multibinding:MultiBinding TargetProperty=”Text” Converter=”{StaticResource MultiBindingGenericConverter}” >

<multibinding:MultiBinding.Bindings>

<multibinding:BindingCollection>

<Binding Path=”Budget” />

<Binding Path=”Budget_Format” />

</multibinding:BindingCollection>

</multibinding:MultiBinding.Bindings>

</multibinding:MultiBinding>

</multibinding:MultiBindings>

</multibinding:BindingUtil.MultiBindings>

</TextBlock>

</DataTemplate>

</data:DataGridTemplateColumn.CellTemplate>

<data:DataGridTemplateColumn.CellEditingTemplate>

<DataTemplate>

<TextBox TextAlignment=”Right” Text=”{Binding Budget, Converter={StaticResource RoundedConverter}, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}” >

</TextBox>

</DataTemplate>

</data:DataGridTemplateColumn.CellEditingTemplate></data:DataGridTemplateColumn>

So if you have a similar scenario, I’d recommend Colin’s solution.

Other issue I had with the DataGrid was with the Virtualization – it’s virtually impossible to deactivate. Also the search for a solution on this was” a bit chaotic… “

I was lucky to find out this gem here http://forums.silverlight.net/forums/t/101075.aspx on which Xusan is telling us not to deactivate it but to change its structure and take out the component that provides the virtualization, changing its ControlTemplate.

That saved my day as the DataGrid really is not “Recycling” but “Reusing”, which I think should be changed or made  optional. As this can be Ok for performance reasons but on others you can end up coding a huge clean-up function that will kill the performance of the virtualization…  if there is a quick way of “cleaning” a row or cell, it would be great this was as fast as possible…

Well, will keep on finishing my DataGrid based project management Silverlight Bizz app 😉 

Have fun!

Simple trick for getting right the DataGrid’s SelectedItem

I have been developing a Silverlight business application and one of the problems I have found is the “inconsistency” of the DataGrid… at least of some of its behaviors, when I click on a row, I expect that the SelectedItem (the clicked one) is set on the corresponding DataGrid property. 

But it does not. at least not “always”, lets be clear maybe I’m doing something wrong but this randomness on this behavior is driving me crazy, if I click on a Grid row, it should select it and mark the SelectedItem on the corresponding property, right? 

I have been doing so in the MouseLeftButtonUp of the DataGrid, so that’s what I expected but… sometimes it had it, sometimes not… bummer! 

So I have been trying to detect why is this happening but could not discover it… maybe I’m wrong in any of the assumptins but meanwhile, I got a workaround that does really work :). 

The following code explains it all… 

void datagrid_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) { 

  if (datagrid.SelectedItem == null){ 

 

      FrameworkElement fe = (e.OriginalSource as FrameworkElement); 

 

      FrameworkElement feCell = (fe.Parent as FrameworkElement); 

 

      var myData = feCell.DataContext; 

  } 

} 

Basically I check first If I have the SelectedItem set, sometimes it is, so then I avoid doing the following trick.

The “trick” mainly gets the originalsource that is launching the event, that is the control inside the cell of the grid,  most of times it will be a TextBox. Second I get the Parent, with this I am getting to the Cell.

Note that if you have a complex structure you should set up a recursive function to go “up” until you get a reference for the cell.

From the cell you have the datacontext which is the item whe should have got from the SelectedItem property.  you should cast it to the inherent type and get any value you need from it.

Also, please note that the DataContext could be caught from the first element (OriginalSource) but it’s more ellegant to get it from the Cell, and if it is a complex custom cell this also asures that it gets the DataContext properly.

And yes, it works 100% 😉

Happy coding!

PS: If somebody knows what I have done wrong or why the DataGrid.SelectedItem Property does not return the clicked item, I would be happy to hear. 🙂