在 DataGrid 内滚动父容器

问题描述 投票:0回答:1

我有这个自定义数据网格。我想要实现的是,当用户将鼠标放在 DataGrid 内部(没有最大高度)时,它应该允许滚动 ScrollViewer 内部的整个父组件。但现在我必须将鼠标移到 DataGrid 之外才能滚动。

下面是我的代码:

 <Style TargetType="{x:Type DataGrid}">
     <Setter Property="Background" Value="Transparent" />
     <Setter Property="VerticalAlignment" Value="Top" />
     <Setter Property="RowDetailsVisibilityMode" Value="Collapsed" />
     <Setter Property="AutoGenerateColumns" Value="False" />
     <Setter Property="IsReadOnly" Value="True" />
     <Setter Property="HeadersVisibility" Value="None" />
     <Setter Property="VerticalContentAlignment" Value="center" />
     <Setter Property="GridLinesVisibility" Value="None" />
     <Setter Property="EnableRowVirtualization" Value="False" />
     <Setter Property="EnableColumnVirtualization" Value="True" />
     <Setter Property="VirtualizingPanel.ScrollUnit" Value="Pixel" />
     <Setter Property="VirtualizingPanel.VirtualizationMode" Value="Standard" />
     <Setter Property="VirtualizingStackPanel.IsVirtualizing" Value="True" />
     <Setter Property="ScrollViewer.CanContentScroll" Value="False" />
     <Setter Property="BorderBrush" Value="Transparent" />
 </Style>

   <ScrollViewer VerticalScrollBarVisibility="Auto"
                 HorizontalScrollBarVisibility="Auto">
       <Grid>
           <Grid.RowDefinitions>
               <RowDefinition Height="Auto" />
               <RowDefinition Height="Auto" />
               <RowDefinition />
           </Grid.RowDefinitions>

       // SOME OTHER COMPONENTS
       <DataGrid ItemsSource="{Binding ListOfUsers}" 
               PreviewMouseWheel="ListView_PreviewMouseWheel">
         // custom rows
       </DataGrid>

背后代码:

private void ListView_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
{
    // Find the ScrollViewer that contains this ListView
    ScrollViewer scrollViewer = FindParentScrollViewer(PatientsListView);
    if (scrollViewer != null)
    {
        // Scroll the ScrollViewer based on the mouse wheel delta
        scrollViewer.ScrollToVerticalOffset(scrollViewer.VerticalOffset - e.Delta);
        e.Handled = true; // Mark the event as handled
    }
}

private ScrollViewer FindParentScrollViewer(DependencyObject child)
{
    if (child is null) return null;

    for (DependencyObject parent = VisualTreeHelper.GetParent(child); parent != null; parent = VisualTreeHelper.GetParent(parent))
    {
        if (parent is ScrollViewer scrollViewer)
            return scrollViewer;
    }
    return null;
}

我尝试将 ScrollViewer.CanContentScroll 值更改为 False 或添加 PreviewMouseWheel 事件,但似乎不起作用。

wpf datagrid scrollviewer
1个回答
0
投票

我偶然发现了这个网页,并将其实施到我的项目中,效果很好: https://serialseb.com/blog/2007/09/03/wpf-tips-6-preventing-scrollviewer-from/

所以,这就是我所做的: 首先,创建一个名为 ScrollViewerCorrector 的类来定义附加属性:

using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

public class ScrollViewerCorrector
{
    public static bool GetFixScrolling(DependencyObject obj)
    {
        return (bool)obj.GetValue(FixScrollingProperty);
    }

    public static void SetFixScrolling(DependencyObject obj, bool value)
    {
        obj.SetValue(FixScrollingProperty, value);
    }

    public static readonly DependencyProperty FixScrollingProperty =
        DependencyProperty.RegisterAttached(
            "FixScrolling",
            typeof(bool),
            typeof(ScrollViewerCorrector),
            new FrameworkPropertyMetadata(false, OnFixScrollingPropertyChanged));

    private static List<MouseWheelEventArgs> _reentrantList = new List<MouseWheelEventArgs>();

    private static void OnFixScrollingPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        if (sender is ScrollViewer viewer)
        {
            if ((bool)e.NewValue)
            {
                viewer.PreviewMouseWheel += HandlePreviewMouseWheel;
            }
            else
            {
                viewer.PreviewMouseWheel -= HandlePreviewMouseWheel;
            }
        }
    }

    private static void HandlePreviewMouseWheel(object sender, MouseWheelEventArgs e)
    {
        var scrollControl = sender as ScrollViewer;

        if (!e.Handled && scrollControl != null && !_reentrantList.Contains(e))
        {
            var previewEventArg = new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta)
            {
                RoutedEvent = UIElement.PreviewMouseWheelEvent,
                Source = sender
            };

            var originalSource = e.OriginalSource as UIElement;
            _reentrantList.Add(previewEventArg);
            originalSource.RaiseEvent(previewEventArg);
            _reentrantList.Remove(previewEventArg);

            if (!previewEventArg.Handled && ((e.Delta > 0 && scrollControl.VerticalOffset == 0) ||
                                              (e.Delta <= 0 && scrollControl.VerticalOffset >= scrollControl.ExtentHeight - scrollControl.ViewportHeight)))
            {
                e.Handled = true;

                var eventArg = new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta)
                {
                    RoutedEvent = UIElement.MouseWheelEvent,
                    Source = sender
                };

                var parent = (UIElement)((FrameworkElement)sender).Parent;
                parent.RaiseEvent(eventArg);
            }
        }
    }
}

接下来,在 XAML 中修改 ScrollViewer 以利用此附加属性。以下是如何将附加属性应用于外部和内部 ScrollViewer 的示例:

<Window x:Class="YourNamespace.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:YourNamespace"
        Title="MainWindow" Height="423" Width="596">

    <Window.Resources>
        <Style TargetType="{x:Type ScrollViewer}">
            <Setter Property="local:ScrollViewerCorrector.FixScrolling" Value="True" />
        </Style>
    </Window.Resources>

    <Grid>
        <ScrollViewer>
            <StackPanel>
                <TextBlock>Content before ListView</TextBlock>

                <ScrollViewer Name="InnerScrollViewer" Height="235">
                    <StackPanel>
                        <TextBlock>Scrollable Content 1</TextBlock>
                        <TextBlock>Scrollable Content 2</TextBlock>
                        <TextBlock>Scrollable Content 3</TextBlock>

                        <ListView Background="Red" ItemsSource="{Binding PatientsNotVerified}">
                            <ListView.ItemTemplate>
                                <DataTemplate>
                                    <StackPanel HorizontalAlignment="Right">
                                        <TextBlock>
                                            <TextBlock.Text>
                                                <MultiBinding StringFormat="{}{0} {1}">
                                                    <Binding Path="FirstName" />
                                                    <Binding Path="LastName" />
                                                </MultiBinding>
                                            </TextBlock.Text>
                                        </TextBlock>
                                        <TextBlock>
                                            <TextBlock.Text>
                                                <MultiBinding StringFormat="{}{0}, {1}">
                                                    <Binding Path="Email" />
                                                    <Binding Path="Cell" />
                                                </MultiBinding>
                                            </TextBlock.Text>
                                        </TextBlock>
                                    </StackPanel>
                                </DataTemplate>
                            </ListView.ItemTemplate>
                        </ListView>
                    </StackPanel>
                </ScrollViewer>

                <TextBlock>Content after ListView</TextBlock>
            </StackPanel>
        </ScrollViewer>
    </Grid>
</Window>
© www.soinside.com 2019 - 2024. All rights reserved.