Webserver Crash!!

June 29th, 2009

I unfortunately had a crash on my webserver.
Currently trying to restore the stuff. But as I’m a little busy this can take a day or two.

Manfred

Silverlight DataGrid & ListBox mouse scroll support

March 15th, 2009

If you read this post you most probably also have the problem that Silverlight 2.0 does not support Mouse Scrolling for the ListBox and DataGrid controls.

I assume that you are comfortable with Silverlight and XAML at this point. If not http://www.silverlight.net/ is a good starting point :-)

There are several articles out on the net on how to implement Mouse Scroll Support for ScrollViewer’s.
But not many on how to use the mouse wheel on DataGrid’s and ListBoxe’s.

One of the best Article I found on ScrollViewer’s is the one from Improved Mouse Wheel Support for Silverlight 2 ScrollViewer from Adam Cooper. He also provides a small library with a working implementation. This site has been down for some days though.
But there are some other articles like http://timheuer.com/blog/archive/2008/09/23/mouse-wheel-support-for-scrollviewer.aspx and http://blogs.msdn.com/coding4fun/archive/2008/09/25/8962691.aspx which describe a basic usage of Adam’s implementation.

I don’t want to go into the details about how this is done as it’s described in the sites mentioned above.

But just a short summary on what you have to do :

  • Attach to the browser mouse scroll events.
  • Implement a listener which handles the scroll event’s
  • find the underlying component where the mouse wheel action has been performed.
  • Scroll the component to the desired position.

 

Now that works all nice if the underlying components implementation uses a ScrollViewer as scroll component.
But that’s unfortunately not true the DataGrid. The ListBox does use a ScrollViewer for scrolling the items, but does not publicly expose the ScrollViewer.

So let’s have first a look a the ListBox as this seems to be the easier case.

 

ListBox Mouse wheel support

As mentioned above, once we can get access to the ScrollViewer within the ListBox it would be easy to extend the existing implementation from Adam Cooper to also work on ListBoxe’s as it works very nice with ScrollViewer’s.

Now the problem is that the ScrollViewer used within the ListBox is not publically available.
To get access to the ScrollViewer within the ListBox I do know about two different ways.

  1. One could traverse down the Component Tree of the ListBox until the ScrollViewer is found.
  2. Extend the ListBox class and expose a public Property ScrollViewer. If the ListBox is extended the ScrollViewer can be accessed by the protected method GetTemplateChild(string childName);

I personally prefer the 2nd way as I don’t want to implement my own traversing code if not really necessary as that’s already done in the GetTemplateChild method which is maintained by Silverlight.

So if we extend the ListBox we end up with something like:

   1:  using System.Windows.Controls;
   2:   
   3:  namespace NystedBerry.Silverlight.Controls
   4:  {
   5:      public class ScrollableListBox: ListBox
   6:      {      
   7:          public ScrollViewer ScrollViewer
   8:          {            
   9:              get
  10:              {
  11:                  return GetTemplateChild("ScrollViewer") as ScrollViewer;
  12:              }
  13:          }
  14:      }
  15:  }

 

Now as we have access to the ScrollViewer within the ListBox it’s straight forward to extend Adam’s implementation for scrolling to also work with ListBoxe’s.

Here just the most important code snipped of the extension.

Download the full source code below to see the complete code.

   1:   public static ScrollableListBox AddMouseWheelSupport(this ScrollViewer parentScrollViewer, ScrollableListBox childListBox, double scrollAmount)
   2:          {
   3:              var mouseWheelHelper = new MouseWheelSupport(childListBox, parentScrollViewer);
   4:              mouseWheelHelper.MouseWheelMoved += (source, eventArgs) =>
   5:              {
   6:   
   7:                  ScrollViewer scrollViewer = childListBox.ScrollViewer;
   8:                  if (scrollViewer == null) return;
   9:   
  10:                  var delta = eventArgs.WheelDelta;
  11:                  delta *= scrollAmount;
  12:                  var newOffset = scrollViewer.VerticalOffset - delta;
  13:   
  14:                  if (newOffset > scrollViewer.ScrollableHeight)
  15:                      newOffset = scrollViewer.ScrollableHeight;
  16:                  else if (newOffset < 0)
  17:                      newOffset = 0;
  18:   
  19:                  scrollViewer.ScrollToVerticalOffset(newOffset);
  20:   
  21:                  eventArgs.BrowserEventHandled = true;
  22:              };
  23:           
  24:              return childListBox;
  25:          }

Note: The ScrollViewer in a ListBox is only available if there are more entries in a ListBox then that can be displayed by the ListBox height configuration.

Ok. Now as the ListBox is clear let’s move on to the DataGrid

 

DataGrid Mouse wheel support

The scrolling support for the DataGrid is unfortunately not implemented by using ScrollViewers to do scrolling.

So we have to find another way to adjust scrolling. And that really was quite a nut to solve.

One thing I found to implement programmatically scrolling for a DataGrid was the method

   1:  public void ScrollIntoView(object item, DataGridColumn column);

However, this method does scroll a certain DataGrid Item into view, but at the same time it’s also selecting the item in the DataGrid. That being a big limitation by itself, using this way proved further difficult as one had to keep the current selected position in the DataGrid. I addition, when mixing that with a scrolling action other then the mouse scroll wheel everything went out of sync…….

So that really was not satisfying implementation.

After having spent far too much time on trying to solve this issue and was close to giving up I stumbled over this article which lightened up everything: http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=351872

There is a description of a workaround by Thomas Hetzer

As a workaround you can derive a ScrollableDataGrid from DataGrid, call OnCreateAutomationPeer and cast the returned AutomationPeer to IScrollProvider. Than you can call IScrollProvider.Scroll with ScrollAmount.SmallDecrement or ScrollAmount.SmallIncrement. It´s a hack but it works.

If we use this Hack and get access to the IScrollProvider we can basically do the same as for the ScrollProviders with the limitation that the amount of scrolling can only be set to two predefined default values. But that proved to be not a big issue.

So to get the IScrollPriovider we do again extend the DataGrid class like:

   1:  using System.Windows.Automation.Provider;
   2:  using System.Windows.Controls;
   3:   
   4:  namespace NystedBerry.Silverlight.Controls
   5:  {
   6:      public class ScrollableDataGrid : DataGrid
   7:      {     
   8:          public IScrollProvider ScrollProvider
   9:          {
  10:              get { return OnCreateAutomationPeer() as IScrollProvider; }
  11:          }
  12:   
  13:      }
  14:  }

Now as we can get the IScrollProvider we can add mouse wheel support like: (again only a snippet)

   1:   public static ScrollableDataGrid AddMouseWheelSupport(this ScrollViewer parentScrollViewer,
   2:              ScrollableDataGrid childDataGrid, ScrollableListBoxScrollAmount scrollAmount)
   3:          {
   4:              var mouseWheelHelper = new MouseWheelSupport(childDataGrid, parentScrollViewer);                
   5:   
   6:              mouseWheelHelper.MouseWheelMoved += (source, eventArgs) =>
   7:              {
   8:                  var delta = eventArgs.WheelDelta;
   9:   
  10:                  if (delta < 0)
  11:                  {
  12:                      childDataGrid.ScrollProvider.Scroll(ScrollAmount.NoAmount,
  13:                          scrollAmount == ScrollableListBoxScrollAmount.Large ? ScrollAmount.LargeIncrement : ScrollAmount.SmallIncrement);
  14:                  } else
  15:                  {
  16:                      childDataGrid.ScrollProvider.Scroll(ScrollAmount.NoAmount, 
  17:                          scrollAmount == ScrollableListBoxScrollAmount.Large ? ScrollAmount.LargeDecrement : ScrollAmount.SmallDecrement);                        
  18:                  }
  19:   
  20:                  eventArgs.BrowserEventHandled = true;
  21:              };
  22:   
  23:              return childDataGrid;
  24:          }       

 

And in XAML yo ucan now use the ScrollableDataGrid instead of the DataGrid.

(don’t forget to include xmlns:Controls="clr-namespace:NystedBerry.Silverlight.Controls"  on the top of your xaml file where you want to use the extended data grid control)

 

<UserControl x:Class="DataGridMouseSupport.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:basics="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"
    xmlns:d=http://schemas.microsoft.com/expression/blend/2008     xmlns:mc=http://schemas.openxmlformats.org/markup-compatibility/2006     xmlns:Controls="clr-namespace:NystedBerry.Silverlight.Controls">
<Controls:ScrollableDataGrid Height="200" x:Name="dataGrid1" Grid.Row="0" Grid.Column="0" Margin="8,8,8,8"/>                     

 

 

You can download the source code here (Updated with additional XAML datagrid column binding)

Demo is here

 

One other Note: I did not want to extend Adam’s Library directly but instead provide an additional very small lib to not mix with his code.

Like that, if he might find issues with his implementation and updates his library, it should be possible to easier upgrade without me having to update the ListBox and DataGrid specific stuff. 
To do so, I however had to change the visibility of the MouseWheelSupport class in his implementation from Internal to Public.

Silverlight and SilverPlay

January 13th, 2009

While developing a first version of a Firefly Media Server client, called SilverPlay, in Silverlight I run unfortunately in many more issues then one could expect when using a Rich Internet Application framework like Silverlight in a version 2.0.

But that’s maybe just me……

The quality of Silverlight as such is pretty ok and luckily there are many bloggers out there which have solved lot’s of the issues I run into. So thanks to all your helpful people!
But most of the problems I run into are really coming from missing features in the current Version.

Those are:

  • No Mouse Scroll support
  • Hard to show html content within a Silverlight app.
  • No Right Mouse button (context menu) support
  • No Drag & Drop out of the box even within a Silverlight object.

As mentioned, most issues are having workarounds/custom implementations described on several blogs and I will not discuss them in detail in this blog again.
I will however post some issues which I think where hard to solve and I didn’t find too much information on the net.

In my next post I will describe on how one can add mouse scroll support to not only scroll viewers itself but also to the OTB ListBox
and DataGrid.

Stand by. :-)

SilverPlay V0.1.1 Released

December 31st, 2008

You can find V0.1.1 of SilverPlay here.

Please comment and suggest on:forums.fireflymediaserver.org