Search code examples
wpf

The scroller does not scroll inside the listbox inside the itemscontrol


I made the following code to illustrate the problem, The goal is to be able to scroll when the mouse is on the Listbox

public List<List<string>> StringList { get; set; } = new() { new() { "A", "B", "C", "D" }, new() { "A", "B", "C", "D" } };


<Grid>
    <ScrollViewer MaxHeight="100">
        <ItemsControl ItemsSource="{Binding Path=StringList}">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Grid>
                        <ListBox ItemsSource="{Binding}">
                            <ListBox.ItemTemplate>
                                <DataTemplate>
                                    <TextBox Text="{Binding Path=.}"/>
                                </DataTemplate>
                            </ListBox.ItemTemplate>
                        </ListBox>
                    </Grid>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </ScrollViewer>
</Grid>

Solution

  • If you want to be able to scroll the outer ScrollViewer (ItemsControl) using the mouse wheel, you could handle the PreviewMouseWheel event for the inner ListBox like this:

    private void ListBox_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
    {
        if (sender is ListBox && !e.Handled)
        {
            e.Handled = true;
            UIElement parent = ((Control)sender).Parent as UIElement;
            parent?.RaiseEvent(new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta)
            {
                RoutedEvent = UIElement.MouseWheelEvent,
                Source = sender
            });
        }
    }
    

    XAML:

    <ScrollViewer MaxHeight="100" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto">
        <ItemsControl ItemsSource="{Binding Path=StringList}">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Grid>
                        <ListBox ItemsSource="{Binding}" PreviewMouseWheel="ListBox_PreviewMouseWheel">
                            <ListBox.ItemTemplate>
                                <DataTemplate>
                                    <TextBox Text="{Binding Path=.}"/>
                                </DataTemplate>
                            </ListBox.ItemTemplate>
                        </ListBox>
                    </Grid>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </ScrollViewer>