1

I have an application that converts mouse events into touch ones so I can use inertia scrolling and other touch features. That code is in the selected answer here:

WPF: Is there a possibility to "route" ordinary mouse events to touch events in Windows 7

The problem I'm having with my ListBox is while I'm flick scrolling, it selects items. Normally touch devices do not select a ListBox item while it's scrolling. What am I missing here?

Here is the xaml I'm using:

<Window x:Class="ScrollingTest.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="600" Width="525">
    <Grid>
        <ListBox x:Name="testListBox"               
                 VirtualizingPanel.ScrollUnit="Pixel" 
                 SelectionMode="Single">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <Border CornerRadius="3" Height="60" Width="480" Background="LightGray" Margin="1">
                        <Label Content="{Binding}"/>
                    </Border>
                </DataTemplate>
            </ListBox.ItemTemplate>               
        </ListBox>
    </Grid>
</Window>

Code behind:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        MouseTouchDevice.RegisterEvents(this);

        for (int i = 0; i < 300; i++)
        {
            testListBox.Items.Add("test " + i.ToString());
        }
    }       
}
Robert
  • 6,086
  • 19
  • 59
  • 84

3 Answers3

0

The only way I found to do this was using a DataTrigger to set the ListBoxItem Focusable property to false. In my case I set the property IsScrolling to false when the user flick scrolls and back when the kenitic movement stops, this stops the selction behaviour while flicking though the list

This solution may not work in your scenario but here is an working example as you may be able to adapt to work for you.

Xaml:

<Window x:Class="WpfApplication13.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Name="UI">
    <Grid DataContext="{Binding ElementName=UI}">
        <ListBox Margin="0,32,0,0" ItemsSource="{Binding List}" ScrollViewer.ScrollChanged="List_ScrollChanged">
            <ListBox.ItemContainerStyle>
                <Style TargetType="{x:Type ListBoxItem}">
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding IsScrolling, ElementName=UI}" Value="True">
                            <Setter Property="IsHitTestVisible" Value="False"/>
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </ListBox.ItemContainerStyle>
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <Button Content="{Binding}" />
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </Grid>
</Window>

Code:

public partial class MainWindow : Window, INotifyPropertyChanged
{

    private ObservableCollection<string> myVar = new ObservableCollection<string>();
    private DateTime _lastScroll;

    public MainWindow()
    {
        InitializeComponent();
        MouseTouchDevice.RegisterEvents(this);
        for (int i = 0; i < 1000; i++)
        {
            List.Add("StackOverflow " + i);
        }
    }

    public ObservableCollection<string> List
    {
        get { return myVar; }
        set { myVar = value; }
    }

    public bool IsScrolling
    {
        get { return !(DateTime.Now > _lastScroll.AddMilliseconds(100)); }
    }

    private void List_ScrollChanged(object sender, ScrollChangedEventArgs e)
    {
        _lastScroll = DateTime.Now;
        ThreadPool.QueueUserWorkItem((o) =>
        {
            Thread.Sleep(100);
            NotifyPropertyChanged("IsScrolling");
        });
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void NotifyPropertyChanged(string property)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(property));
        }
    }
}
sa_ddam213
  • 42,848
  • 7
  • 101
  • 110
  • I think this is a clever solution, but it has some issues. The first one is if the item template contains a button, setting the container style to not focusable will still allow the button click and command to be fired. The other issue is it's not very reusable, I have about 35 view models that will need to implement this behavior MVVM style and this does work quite right. – Robert Jan 06 '13 at 23:10
  • I have updated the answer to work on `ItemTemplates` in this case we set `IsHitTestVisible` to false instead of `Focusable` now we just need to find a nice way to notify `IsScrolling` , I will have a play and try find a generic way to do this. – sa_ddam213 Jan 06 '13 at 23:48
  • I have updated my answer with an example that works quite well, it may not be the most glamorous solution but I think it will work for your situation(worked for mine:) ) – sa_ddam213 Feb 22 '13 at 07:10
  • This doesn't work, item selection still occurs on the first scroll. – Robert Feb 23 '13 at 18:41
  • How would you like to select Items, how will it know you want to scroll or want to select, perhaps you need a "Touch and Hold" selection or another gesture – sa_ddam213 Feb 23 '13 at 22:32
  • I would have selection occur on the mouse up event instead of the mouse down event on the listbox. – Robert Feb 25 '13 at 17:26
0

I think this can be achieved using Adorners.

MSDN Samples http://msdn.microsoft.com/en-us/library/ms771585(VS.85).aspx

Adorners are very simple; it can be very well used here. Refer the below link, you can make the adorner layer background to transparent if the overlay is not preferred.

http://www.codeproject.com/Articles/57984/WPF-Loading-Wait-Adorner

Liju
  • 91
  • 4
0

I know this is an old question but I have a confirmed solution. Setting the ScrollViewer.PanningMode property enables touch scrolling and thus prevents the selection on MouseUp. Just set PanningMode="VerticalOnly", for example, for a simple scrolling scenario and you should be all good.

Hope I helped someone

TomerAgmon1
  • 295
  • 3
  • 10