ScrollViewer 无法与 GroupBox 上的 MouseWheel 配合使用

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

我正在尝试让滚动查看器在自定义样式的组框中工作。 这是组框的样式:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

<!--Set default style of groupbox-->
<Style TargetType="GroupBox">
    <Setter Property="Margin" Value="0, 10, 0, 0"></Setter>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="GroupBox">
                <Border CornerRadius="4" BorderThickness="1" BorderBrush="{StaticResource BorderBrush}" Background="{StaticResource ContentBackgroundBrush}">
                    <ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
                        <StackPanel Orientation="Vertical" CanVerticallyScroll="True">
                            <Label Content="{TemplateBinding Header}" Margin="5,5,0,0" Style="{StaticResource SmallTitle}"></Label>
                            <ContentPresenter Margin="10, 5, 10, 10" RecognizesAccessKey="True" x:Name="CtlGroupboxPresenter" />
                        </StackPanel>
                    </ScrollViewer>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

出现了滚动条,但无法使用鼠标滚轮滚动。但是,当我的鼠标悬停在垂直滚动条上时,它会起作用。这似乎是一个跟踪问题。

我看到一些人建议在代码后面添加一些代码以使其正常工作,但由于这是在资源字典中,所以我没有地方可以放置它......

有谁知道是什么问题吗?

这是 wpf 表单的图像: enter image description here

组框内的 XAML:

<UserControl x:Class="Sun.Plasma.Controls.ViewNews"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008">
<DockPanel LastChildFill="True">
    <Label DockPanel.Dock="Top" Style="{StaticResource LblTitle}" FontWeight="Bold" FontSize="24" >Latest SUN news &amp; announcements</Label>

    <StackPanel Orientation="Vertical" VerticalAlignment="Stretch">
        <StackPanel Orientation="Vertical" Name="CtlLoadingNews">
            <Label Style="{StaticResource LblContent}">Loading content from server...</Label>
            <ProgressBar IsIndeterminate="True" Height="30" />
        </StackPanel>
        <ListView Background="Transparent" DockPanel.Dock="Bottom" ItemsSource="{Binding NewsFeeds}" BorderBrush="Transparent" Name="CtlNews" Visibility="Collapsed">

            <!-- Defining these resources prevents the items from appearing as selectable -->
            <ListView.Resources>
                <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Transparent" />
                <SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}" Color="Black" />
                <SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="Transparent" />
            </ListView.Resources>

            <ListView.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Vertical" Margin="0 0 0 20">
                        <Label Style="{StaticResource LblTitle}" FontWeight="Bold" Content="{Binding Title}" />
                        <StackPanel Orientation="Horizontal">
                            <Label Style="{StaticResource LblFooter}" Content="{Binding PublishDate}" />
                            <Label Style="{StaticResource LblFooter}">By</Label>
                            <Label Style="{StaticResource LblFooter}" Content="{Binding Authors[0]}" />
                            <Label Style="{StaticResource LblFooter}">
                                <Hyperlink RequestNavigate="Hyperlink_RequestNavigate" NavigateUri="{Binding Source}">Read entry</Hyperlink>
                            </Label>
                        </StackPanel>
                    </StackPanel>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </StackPanel>
</DockPanel>

c# .net wpf
2个回答
2
投票

问题在于,

ListView
内容中的
GroupBox
阻止了
MouseWheel
事件冒泡到
ScrollViewer
。我找到了一个 hacky 解决方案:

您可以处理内部

PreviewMouseWheel
上的
ListView
事件,并直接在滚动查看器上引发
MouseWheel
事件。

private void ListView_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
{
    if (!e.Handled)
    {
        e.Handled = true;
        var eventArg = new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta);
        eventArg.RoutedEvent = UIElement.MouseWheelEvent;
        eventArg.Source = sender;
        //navigate to the containing scrollbar and raise the MouseWheel event
        (((sender as ListView).Parent as GroupBox).Content as ListView).RaiseEvent(eventArg);
    }
}

再次强调,这不是我特别喜欢的解决方案,因为它依赖于

GroupBox
的布局。

第二种稍微好一点的方法是向

GroupBox
的资源添加样式,在其中向
PreviewMouseWheel
事件添加处理程序:

<GroupBox Header="test">
    <GroupBox.Resources>
        <Style TargetType="ScrollViewer">
            <EventSetter Event="PreviewMouseWheel" Handler="ScrollViewer_PreviewMouseWheel" />
        </Style>
    </GroupBox.Resources>
    <!-- your contents -->
</GroupBox>

事件处理程序然后执行滚动:

private void ScrollViewer_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
{
    var scrollViewer = sender as ScrollViewer;
    double change = e.Delta;
    double currentPosition = scrollViewer.VerticalOffset;

    scrollViewer.ScrollToVerticalOffset(currentPosition - change);
}

0
投票

受到@Domysee的启发,但我的事件不是由滚动查看器触发的,可能是因为布局不同

XAML:

<GroupBox Header="Services">
<Grid PreviewMouseWheel="OnScroll">
    <ScrollViewer x:Name="_scrollViewer" VerticalScrollBarVisibility="Auto">
        <StackPanel Orientation="Vertical">
            <ScrollViewer VerticalScrollBarVisibility="Auto">
                <ItemsControl ItemsSource="{Binding Services}">
                    <ItemsControl.ItemsPanel>
                        <ItemsPanelTemplate>
                            <UniformGrid Columns="2" />
                        </ItemsPanelTemplate>
                    </ItemsControl.ItemsPanel>
                </ItemsControl>
            </ScrollViewer>

            <Button Width="50"
                    HorizontalAlignment="Left"
                    Command="{Binding NewServiceCommand}"
                    Content="+" />
        </StackPanel>
    </ScrollViewer>
    <Grid 
         <!-- overlay goes here -->
    </Grid>
</Grid>
</GroupBox>

背后代码:

private void OnScroll(object sender, MouseWheelEventArgs e)
{
    double change = e.Delta;
    double currentPosition = _scrollViewer.VerticalOffset;

    _scrollViewer.ScrollToVerticalOffset(currentPosition - change);
}
© www.soinside.com 2019 - 2024. All rights reserved.