在嵌套的 TabControl 中滚动

Scrolling in nested TabControl

我有一个使用选项卡控件的 wpf 应用程序。结构如下所示:

/*MainView*/
<UserControl>
    <UserControl.Resources>
        <DataTemplate DataType="{x:Type tapViewModels:TabViewModel}">
            <tabViews:TabView />
        </DataTemplate>
    </UserControl.Resources>
    <ScrollViewer Name="MainScrollViewer" VerticalScrollBarVisibility="Auto">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition />
                <RowDefinition />
            </Grid.RowDefinitions>
            <Grid Grid.Row="0">
                ...
            </Grid>
            <Grid Grid.Row="1">
                <dx:DXTabControl ItemsSource="{Binding TabItems}" SelectedIndex="0">
                    <dx:DXTabControl.ItemHeaderTemplate>
                        <DataTemplate>
                            <TextBlock Text="{Binding Path=Header}" />
                        </DataTemplate>
                    </dx:DXTabControl.ItemHeaderTemplate>
                    <dx:DXTabControl.ItemTemplate>
                        <DataTemplate>
                            <ContentControl Content="{Binding Path=Content}" />     /*Content = new TabViewModel()*/
                        </DataTemplate>
                    </dx:DXTabControl.ItemTemplate>
                </dx:DXTabControl>
            </Grid>
        </Grid>
    </ScrollViewer>
</UserControl>

/*TabView*/
<UserControl>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>
        <Grid Grid.Row="0">
            ...
        </Grid>
        <Grid Grid.Row="1">
            <dxg:GridControl>
                <dxg:TableView>
                   ...
                </dxg:TableView>
            </dxg:GridControl>
        </Grid>
    </Grid>
</UserControl>

当我在悬停 GridControl 的同时向上滚动时,如果 GridControl 已经滚动到顶部,我希望滚动事件 "bubble" 向上。当然,当在底部蜂鸣时向下滚动时也是如此。

我的问题是,GridControl 和 ScrollViewer 存在于两个不同的视图中,并且具有两个不同的 ViewModel。那么我怎样才能使它起作用呢?

我会喜欢。一个 MVVM 解决方案,但此时我对任何事情都持开放态度!

可以处理下层控件的MouseWheel事件,判断是否滚动到顶部,再引发上层控件的事件:

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition />
        <RowDefinition />
    </Grid.RowDefinitions>
    <wpfApplication3:ControlA x:Name="A" Grid.Row="0" />
    <wpfApplication3:ControlB x:Name="B" Grid.Row="1" PreviewMouseWheel="HandleMouseWheel"/>
</Grid>

然后在 HandleMouseWheel 事件中:

private void HandleMouseWheel(object sender, MouseWheelEventArgs e)
    {
        var controlB = sender as ControlB;

        if (controlB != null && e.Delta > 0 && controlB.Scroll.VerticalOffset == 0)
        {
            e.Handled = true;

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

            A.Scroll.RaiseEvent(eventArg);
        }
    }

e.Delta 检查您是否向上滚动鼠标,VerticalOffset 检查确保控件已经滚动到顶部。

这假设您的用户控件中有一个公开可用的滚动查看器,例如:

<UserControl>
    <ScrollViewer x:Name="Scroll">
        <Grid Height="1000"></Grid>
    </ScrollViewer>
</UserControl>