ScrollViewer 中的 WPF DataGrid

WPF DataGrid inside a ScrollViewer

我有一个带有 header 控件的 StackPanel 和一个 Scrollviewer 内部的 DataGrid;像这样:

<ScrollViewer>
    <StackPanel Orientation="Vertical">
        <Canvas x:Name="header" 
                Height="300" />
        <DataGrid x:Name="dataGrid">
        </DataGrid>
    </StackPanel>
</ScrollViewer>

scoll 行为应满足这些要求:

我尝试了 DataGrid.ScrollViewer 的各种设置,但 none 有预期的效果,也没有将 StackPanel 更改为 WrapPanel 甚至 Grid帮助任何。

这可能吗?感谢任何阅读帮助和资源。

这是一个非常复杂的问题,可能需要 man-week 才能完成!但这是解决一半问题的开始:

<ScrollViewer x:Name="scroll">
    <DataGrid x:Name="dataGrid">
        <DataGrid.Template>
            <ControlTemplate>
                <StackPanel Orientation="Vertical">
                    <Canvas x:Name="header" Height="300" />
                    <ItemsPresenter/>
                </StackPanel>
            </ControlTemplate>
        </DataGrid.Template>
    </DataGrid>
</ScrollViewer>

如果您将 canvas 放入数据网格的模板中,它会将其视为数据网格的一部分,因此 canvas 和数据网格将作为一个整体滚动。

显然,数据网格模板将是空白的,不显示 headers。因此,您需要从头开始重写它。为此,您可以使用 the default source code

要查找模板,只需搜索 <ControlTemplate TargetType="{x:Type DataGrid}"> 在给定的 link.

我也为您的第一个问题苦苦挣扎了一段时间 - 让内部 ScrollViewer(在本例中为 DataGrid)滚动外部 ScrollViewer。但我认为我有一个非常优雅的解决方案。您必须向 DataGrid 的 PreviewMouseWheel 事件添加事件处理程序(以及 ScrollViewer 的名称):

<ScrollViewer x:Name="scroll_viewer">
    <StackPanel Orientation="Vertical">
        <Canvas x:Name="header" 
                Height="300" />
        <DataGrid x:Name="dataGrid" PreviewMouseWheel="mousewheel">
        </DataGrid>
    </StackPanel>
</ScrollViewer>

然后事件处理方法:

private void mousewheel(object sender, MouseWheelEventArgs e)
{
    //what we're doing here, is that we're invoking the "MouseWheel" event of the parent ScrollViewer.

    //first, we make the object with the event arguments (using the values from the current event)
    var args = new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta);

    //then we need to set the event that we're invoking.
    //the ScrollViewer control internally does the scrolling on MouseWheelEvent, so that's what we're going to use:
    args.RoutedEvent = ScrollViewer.MouseWheelEvent;

    //and finally, we raise the event on the parent ScrollViewer.
    scroll_viewer.RaiseEvent(args);
}

希望对您有所帮助!