I have found the answer, so I will answer myself.
1) How to make the ListBox scroll smoothly :
This problem did not happen in SilverLight 2, and it happens only with SilverLight 3, in which the VirtualizedStackPanel was introduced.
The VirtualizedStackPanel enables much faster refresh in the case of huge lists (as only the visible elements are drawn)
There is a workaround for this (beware, it should not be used on huge lists) : you redefine the ListBox's ItemPanelTemplate, so that it uses StackPanel :
<navigation:Page.Resources>
<ItemsPanelTemplate x:Key="ItemsPanelTemplate">
<StackPanel/>
</ItemsPanelTemplate>
</navigation:Page.Resources>
<StackPanel Orientation="Vertical" x:Name="LayoutRoot">
<ListBox x:Name="list" ItemsPanel="{StaticResource ItemsPanelTemplate}">
</ListBox>
</StackPanel>
2) How to programatically change the scrolling position
See the subclass of ListBox below : it provides an accessor to the internal ScrollViewer of the ListBox
3) How to catch the MouseDown / Move / Up events in the listbox :
Create a subclass of ListBox as shown below. The 3 methods :
internal void MyOnMouseLeftButtonDown(MouseButtonEventArgs e)
protected override void OnMouseMove(MouseEventArgs e)
protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e)
will be called and you can do whatever you want with them. There is one subtle trick which is that the OnMouseLeftButtonDown method of ListBox is never called : you need to implement a subclass of ListBoxItem where you can handle this event.
using System;
using System.Collections.Generic;
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;
namespace MyControls
{
//In order for this class to be usable as a control, you need to create a folder
//named "generic" in your project, and a "generic.xaml" file in this folder
//(this is where you can edit the default look of your controls)
//
/*
* Typical content of an "empty" generic.xaml file :
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:VideoControls">
</ResourceDictionary>
*/
public class MyListBox : ListBox
{
public MyListBox()
{
DefaultStyleKey = typeof(ListBox);
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
}
#region ScrollViewer / unlocking access related code
private ScrollViewer _scrollHost;
public ScrollViewer ScrollViewer
{
get
{
if (_scrollHost == null)
_scrollHost = FindVisualChildOfType<ScrollViewer>(this);
return _scrollHost;
}
}
public static childItemType FindVisualChildOfType<childItemType>(DependencyObject obj)
where childItemType : DependencyObject
{
// Search immediate children first (breadth-first)
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(obj, i);
if (child != null && child is childItemType)
return (childItemType)child;
else
{
childItemType childOfChild = FindVisualChildOfType<childItemType>(child);
if (childOfChild != null)
return childOfChild;
}
}
return null;
}
#endregion
//Modify MyListBox so that it uses MyListBoxItem instead of ListBoxItem
protected override DependencyObject GetContainerForItemOverride()
{
MyListBoxItem item = new MyListBoxItem(this);
if (base.ItemContainerStyle != null)
{
item.Style = base.ItemContainerStyle;
}
return item;
}
//OnMouseLeftButtonUp is never reached, since it is eaten by the Items in the list...
/*
protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
{
base.OnMouseLeftButtonDown(e);
e.Handled = false;
}
*/
internal void MyOnMouseLeftButtonDown(MouseButtonEventArgs e)
{
}
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
}
protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e)
{
base.OnMouseLeftButtonUp(e);
}
}
public class MyListBoxItem : ListBoxItem
{
MyListBox _customListBoxContainer;
public MyListBoxItem()
{ }
public MyListBoxItem(MyListBox customListBox)
{
this._customListBoxContainer = customListBox;
}
protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
{
base.OnMouseLeftButtonDown(e);
if (this._customListBoxContainer != null)
{
this._customListBoxContainer.MyOnMouseLeftButtonDown(e);
}
}
}
}