ScrollViewer 上的 DataGrid 阻止其滚动

发布于 2024-11-10 08:20:15 字数 205 浏览 5 评论 0原文

我在 ScrollViewer 上放置了多个 DataGrid。 这些 DataGrid 具有“height: auto”属性,以便我可以隐藏滚动条并查看所有内容。 唯一的问题是 DataGrid 获得焦点,因此我无法滚动 ScrollViewer。 该属性是否可以将焦点保持在 ScrollViewer 上,同时也保持 DataGrid 的行为(以便我可以选择元素)?

谢谢 !

I have multiples DataGrids disposed over a ScrollViewer.
These DataGrids have an "height: auto" property so that I can hide the scrollbar and view all the content.
The only problem is that the DataGrids takes the focus and so I can't scroll the ScrollViewer.
Is that a property to keep the focus on the ScrollViewer but also keeping the behaviour of the DataGrids (so I can select elements) ?

Thank you !

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

穿透光 2024-11-17 08:20:15

为时已晚,但我以这种方式解决了这个问题:
我为 DataGrid 创建了 PreviewMouseWheel 事件
并手动滚动包装ScrollViewer

private void dgInvoicesItems_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
{
this.scrInvoice.ScrollToVerticalOffset(this.scrInvoice.ContentVerticalOffset - e.Delta);
}

It's to late, but I resolved this problem in this manner:
I created the PreviewMouseWheel event for DataGrid
and manually scrolled the wrapping ScrollViewer

private void dgInvoicesItems_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
{
this.scrInvoice.ScrollToVerticalOffset(this.scrInvoice.ContentVerticalOffset - e.Delta);
}
请恋爱 2024-11-17 08:20:15

我遇到了这个完全相同的问题,只是我的情况有点复杂。我的 ScrollViewer 中没有使用 DataGrid,而是使用了一堆 UserControl(称为 ProductDataGrid,定义如下):

ProductDataGrid.xaml:

<UserControl x:Class="My.Control.ProductDataGrid" ...>
    <Grid>
        <Grid.RowDefinitions>...</Grid.RowDefinitions>

        <TextBlock x:Name="Header" Grid.Row="0" ... />

        <DataGrid x:Name="ProductData" Grid.Row="1" ... />
    </Grid>
</UserControl>

ProductPortfolioListView.xaml:

<Page ...
      xmlns:my="clr-namespace:My.Control"
      ....>
    <Grid>
        <Grid.RowDefinitions>...</Grid.RowDefinitions>

        <ScrollViewer x:Name="ProductScrollViewer">
            <StackPanel>
                <my:ProductDataGrid ... />

                <my:ProductDataGrid ... />

                <my:ProductDataGrid ... />
            </StackPanel>
        </ScrollViewer>

Livsi 提供的解决方案是正确的,但我的 UserControl 无权访问我的 ScrollViewer,所以这是我的解决方案:

ProductPortfolioListView.xaml:

<Page ...
      xmlns:my="clr-namespace:My.Control"
      ....>
    <Grid>
        <Grid.RowDefinitions>...</Grid.RowDefinitions>

        <ScrollViewer x:Name="ProductScrollViewer">
            <StackPanel>
                <my:ProductDataGrid ... 
                        PreviewMouseWheel="ProductDataGrid_PreviewMouseWheel" />

                <my:ProductDataGrid ... 
                        PreviewMouseWheel="ProductDataGrid_PreviewMouseWheel" />

                <my:ProductDataGrid ... 
                        PreviewMouseWheel="ProductDataGrid_PreviewMouseWheel" />
            </StackPanel>
        </ScrollViewer>

ProductPortfolioListView.xaml.cs:

void ProductDataGrid_PreviewMouseWheel(object sender, MouseWheelEventArgs args)
{
    ProductScrollViewer.ScrollToVerticalOffset(ProductScrollViewer.ContentVerticalOffset - args.Delta;
    args.Handled = true;
}

请注意此解决方案的优点在于我可以将 DataGrid 与保存它们的页面分开,因此我实现了代码隔离以及更少的重复代码。更好的是,我绝对利用了这样一个事实:RoatedEvents 不断从源传播到其所有父级,直到有人处理它(在我的例子中是我的 ProductScrollViewer)。

I ran across this exact same issue except my scenario was a little bit more complicated. Instead of having DataGrid in a ScrollViewer, I had a bunch of UserControl (called ProductDataGrid and defined below) in my ScrollViewer:

ProductDataGrid.xaml:

<UserControl x:Class="My.Control.ProductDataGrid" ...>
    <Grid>
        <Grid.RowDefinitions>...</Grid.RowDefinitions>

        <TextBlock x:Name="Header" Grid.Row="0" ... />

        <DataGrid x:Name="ProductData" Grid.Row="1" ... />
    </Grid>
</UserControl>

ProductPortfolioListView.xaml:

<Page ...
      xmlns:my="clr-namespace:My.Control"
      ....>
    <Grid>
        <Grid.RowDefinitions>...</Grid.RowDefinitions>

        <ScrollViewer x:Name="ProductScrollViewer">
            <StackPanel>
                <my:ProductDataGrid ... />

                <my:ProductDataGrid ... />

                <my:ProductDataGrid ... />
            </StackPanel>
        </ScrollViewer>

The solution provided by Livsi is spot on correct but my UserControl did not have access to my ScrollViewer, so here is my solution:

ProductPortfolioListView.xaml:

<Page ...
      xmlns:my="clr-namespace:My.Control"
      ....>
    <Grid>
        <Grid.RowDefinitions>...</Grid.RowDefinitions>

        <ScrollViewer x:Name="ProductScrollViewer">
            <StackPanel>
                <my:ProductDataGrid ... 
                        PreviewMouseWheel="ProductDataGrid_PreviewMouseWheel" />

                <my:ProductDataGrid ... 
                        PreviewMouseWheel="ProductDataGrid_PreviewMouseWheel" />

                <my:ProductDataGrid ... 
                        PreviewMouseWheel="ProductDataGrid_PreviewMouseWheel" />
            </StackPanel>
        </ScrollViewer>

ProductPortfolioListView.xaml.cs:

void ProductDataGrid_PreviewMouseWheel(object sender, MouseWheelEventArgs args)
{
    ProductScrollViewer.ScrollToVerticalOffset(ProductScrollViewer.ContentVerticalOffset - args.Delta;
    args.Handled = true;
}

Note the beauty of this solution lies in the fact that I can separate my DataGrid from the Page that will hold them, so I achieve code isolation as well as less duplicated code. And even better, I absolutely utilize the fact that RoutedEvents keep propragating from the Source to all of its parents until someone handles it (which in my case is my ProductScrollViewer).

浮生未歇 2024-11-17 08:20:15

TopMouseScrollPriorityBehavior.TopMouseScrollPriority

您只需将以下附加属性设置为您的 ScrollViewer

public class TopMouseScrollPriorityBehavior
{
    public static bool GetTopMouseScrollPriority(DependencyObject obj)
    {
        return (bool)obj.GetValue(TopMouseScrollPriorityProperty);
    }

    public static void SetTopMouseScrollPriority(DependencyObject obj, bool value)
    {
        obj.SetValue(TopMouseScrollPriorityProperty, value);
    }

    public static readonly DependencyProperty TopMouseScrollPriorityProperty =
        DependencyProperty.RegisterAttached("TopMouseScrollPriority", typeof(bool), typeof(TopMouseScrollPriorityBehavior), new PropertyMetadata(false, OnPropertyChanged));

    private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var scrollViewer = d as ScrollViewer;
        if (scrollViewer == null)
            throw new InvalidOperationException($"{nameof(TopMouseScrollPriorityBehavior)}.{nameof(TopMouseScrollPriorityProperty)} can only be applied to controls of type {nameof(ScrollViewer)}");
        if (e.NewValue == e.OldValue)
            return;
        if ((bool)e.NewValue)
            scrollViewer.PreviewMouseWheel += ScrollViewer_PreviewMouseWheel;
        else
            scrollViewer.PreviewMouseWheel -= ScrollViewer_PreviewMouseWheel;
    }

    private static void ScrollViewer_PreviewMouseWheel(object sender, System.Windows.Input.MouseWheelEventArgs e)
    {
        var scrollViewer = (ScrollViewer)sender;
        scrollViewer.ScrollToVerticalOffset(scrollViewer.VerticalOffset - e.Delta);
        e.Handled = true;
    }
}

用法

<ScrollViewer b:TopMouseScrollPriorityBehavior.TopMouseScrollPriority="True" VerticalScrollBarVisibility="Auto" Margin="5" PanningMode="VerticalFirst">
    <DataGrid ScrollViewer.PanningMode="None" ItemsSource="{Binding Items}" />
</ScrollViewer>

其中 b: 是包含此行为的命名空间

Touch支持

要启用触摸支持,您可能还需要在 DataGrid 上将 ScrollViewer.PanningMode 设置为 None,并将相同的属性设置为VerticalFirst 或顶级 ScrollViewer 上的其他值

示例

<ScrollViewer VerticalScrollBarVisibility="Auto" Margin="5" PanningMode="VerticalFirst">
    <DataGrid ScrollViewer.PanningMode="None" ItemsSource="{Binding Items}" />
</ScrollViewer>

TopMouseScrollPriorityBehavior.TopMouseScrollPriority

You can simply set the following Attached Property to your ScrollViewer

public class TopMouseScrollPriorityBehavior
{
    public static bool GetTopMouseScrollPriority(DependencyObject obj)
    {
        return (bool)obj.GetValue(TopMouseScrollPriorityProperty);
    }

    public static void SetTopMouseScrollPriority(DependencyObject obj, bool value)
    {
        obj.SetValue(TopMouseScrollPriorityProperty, value);
    }

    public static readonly DependencyProperty TopMouseScrollPriorityProperty =
        DependencyProperty.RegisterAttached("TopMouseScrollPriority", typeof(bool), typeof(TopMouseScrollPriorityBehavior), new PropertyMetadata(false, OnPropertyChanged));

    private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var scrollViewer = d as ScrollViewer;
        if (scrollViewer == null)
            throw new InvalidOperationException($"{nameof(TopMouseScrollPriorityBehavior)}.{nameof(TopMouseScrollPriorityProperty)} can only be applied to controls of type {nameof(ScrollViewer)}");
        if (e.NewValue == e.OldValue)
            return;
        if ((bool)e.NewValue)
            scrollViewer.PreviewMouseWheel += ScrollViewer_PreviewMouseWheel;
        else
            scrollViewer.PreviewMouseWheel -= ScrollViewer_PreviewMouseWheel;
    }

    private static void ScrollViewer_PreviewMouseWheel(object sender, System.Windows.Input.MouseWheelEventArgs e)
    {
        var scrollViewer = (ScrollViewer)sender;
        scrollViewer.ScrollToVerticalOffset(scrollViewer.VerticalOffset - e.Delta);
        e.Handled = true;
    }
}

Usage

<ScrollViewer b:TopMouseScrollPriorityBehavior.TopMouseScrollPriority="True" VerticalScrollBarVisibility="Auto" Margin="5" PanningMode="VerticalFirst">
    <DataGrid ScrollViewer.PanningMode="None" ItemsSource="{Binding Items}" />
</ScrollViewer>

Where b: is the namespace that contains this behavior

Touch Support

To enable touch support you might also want to set ScrollViewer.PanningMode to None on your DataGrid and set the same property to VerticalFirst or other value on your top level ScrollViewer

Example

<ScrollViewer VerticalScrollBarVisibility="Auto" Margin="5" PanningMode="VerticalFirst">
    <DataGrid ScrollViewer.PanningMode="None" ItemsSource="{Binding Items}" />
</ScrollViewer>
上课铃就是安魂曲 2024-11-17 08:20:15

尝试将 DataGrid 上的 CanContentScroll 设置为 False,如下所示:

<DataGrid ScrollViewer.CanContentScroll="False" ... />

Try setting the CanContentScroll on the DataGrid to False like this:

<DataGrid ScrollViewer.CanContentScroll="False" ... />
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文