WPF滚动条和焦点切换问题

3
我在我的WPF应用程序中遇到了滚动问题。
我的UI如下所示:
我的应用程序的作用是作为许多应用程序的中央枢纽并启动它们。管理员可以启动由另一个用户记录的转储。
因此,我有一个ListView,显示应用程序列表,如果需要,可以滚动。我定义了一个GroupStyle以显示扩展器并模拟Windows资源管理器视图。
一切都很好,只是我有一个问题:当使用鼠标滚轮滚动时,清晰蓝色组件(“启动模式”)似乎会捕捉焦点并停止滚动。
这意味着特别是如果我的鼠标在此控件之外的任何地方,滚动就没问题。但是每当鼠标进入此控件时,我就无法再滚动了。
我尝试修改Focusable属性,并将其设置为False,但没有任何改变。我猜最终不是一个焦点问题。
有人有想法如何避免被元素捕获滚动吗?
以下是扩展器内容的XAML(已简化,删除了一些无用的属性,以使其尽可能清晰)。
<StackPanel Orientation="Vertical"  VerticalAlignment="Top" >

            <ToggleButton>
                <!-- ToggleButton Content... -->
            </ToggleButton>

            <!-- This is the custom component in which you can see "Launch mode" -->
            <my:UcReleaseChooser >
                <!-- Properties there. I tried to set Focusable to False, no impact... -->
            </my:UcReleaseChooser>

        </StackPanel>

UcReleaseChooser 的代码如下:

<StackPanel HorizontalAlignment="Stretch"
                Focusable="False" ScrollViewer.CanContentScroll="False">

        <ListBox ItemsSource="{Binding ListChosenReleases}" BorderBrush="LightGray" Background="AliceBlue"
                 HorizontalAlignment="Stretch" Focusable="False" ScrollViewer.CanContentScroll="False">

            <ListBox.ItemsPanel>
                <ItemsPanelTemplate>
                    <StackPanel Orientation="Vertical" 
                                Focusable="False" ScrollViewer.CanContentScroll="False"/>
                </ItemsPanelTemplate>
            </ListBox.ItemsPanel>

            <ListBox.ItemTemplate>
                <DataTemplate>
                    <DockPanel LastChildFill="True" HorizontalAlignment="Stretch"
                               Focusable="False" ScrollViewer.CanContentScroll="False">
                        <TextBlock DockPanel.Dock="Top"
                            HorizontalAlignment="Left" Text="{Binding Key}" 
                                   FontStyle="Italic"/>
                        <ListBox DockPanel.Dock="Bottom"
                            HorizontalAlignment="Right" ItemsSource="{Binding Value}"
                                 BorderBrush="{x:Null}" Background="AliceBlue"
                                 Focusable="False" ScrollViewer.CanContentScroll="False">
                            <ListBox.ItemsPanel>
                                <ItemsPanelTemplate>
                                    <UniformGrid Focusable="False"/>
                                </ItemsPanelTemplate>
                            </ListBox.ItemsPanel>

                            <ListBox.ItemContainerStyle>
                                <Style TargetType="{x:Type ListBoxItem}">
                                    <-- Blah blah about style -->
                                </Style>
                            </ListBox.ItemContainerStyle>


                            <ListBox.ItemTemplate>
                                <DataTemplate>
                                    <RadioButton Content="{Binding Key}" Margin="3"
                                            IsChecked="{Binding Path=IsSelected, Mode=TwoWay, 
                                                        RelativeSource={RelativeSource FindAncestor, 
                                                            AncestorType={x:Type ListBoxItem}}}" 
                                                 Focusable="False" ScrollViewer.CanContentScroll="False"/>
                                </DataTemplate>
                            </ListBox.ItemTemplate>
                        </ListBox>
                    </DockPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>

        </ListBox>

    </StackPanel>

如您所见,UcReleaseChooser 包含一系列 RadioButton 列表。我尝试在适当的位置设置 FocusableCanContentScrollFalse,但该控件仍然会阻止主 UI 滚动...
我猜我应该改变另一个属性... 有什么建议吗?
谢谢!
2个回答

1
问题出在ListBox,更具体地说,是ListBox模板中的ScrollViewer。这会获取您的滚动事件并在外部ListView看到它们之前将其消耗掉。
如果可能的话,我建议用ItemsControl替换ListBox。然而,这意味着将没有SelectedItem属性。如果您需要它,我建议将ScrollViewer.HorizontalScrollBarVisibility(或VerticalScrollBarVisibility)设置为Disabled。如果失败了,我只能建议重新设计ListBox,不包含任何ScrollViewer

嗨,感谢您的帮助。将 ScrollBarVisibility 设置为 Disabled 没有改变任何东西,而且重新模板化 ListBox 对我来说似乎太困难了。因此,我使用了 Simon Fox 在这个 stackoverflow 问题中描述的技巧:https://dev59.com/mHI95IYBdhLWcg3wtwRe :) 不管怎样,还是感谢您确认我的问题! - Damascus

1
我遇到了一个问题,就是在一个滚动视图中(我有多个列表框),一个列表框会窃取焦点。因此,我创建了一个附加属性,禁止列表框滚动。这样,容纳列表框的滚动视图可以滚动。
你的控件是列表框,所以这应该可以直接使用,但没有理由限制扩展只能用于列表框;它只是为了匹配我的确切目的而已。
 public static class ListboxExtensions
{
    public static DependencyProperty IgnoreScrollProperty = DependencyProperty.RegisterAttached("IgnoreScroll", typeof(bool), typeof(ListboxExtensions), new UIPropertyMetadata(false, IgnoreScrollChanged));

    public static bool GetIgnoreScroll(DependencyObject dependencyObject)
    {
        return (bool)dependencyObject.GetValue(IgnoreScrollProperty);
    }

    public static void SetIgnoreScroll(DependencyObject dependencyObject, bool value)
    {
        dependencyObject.SetValue(IgnoreScrollProperty, value);
    }

    private static void IgnoreScrollChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var newValue = (bool)e.NewValue;
        var oldValue = (bool)e.OldValue;

        var frameworkElement = d as FrameworkElement;
        if (frameworkElement == null) return;

        if (!newValue || oldValue || frameworkElement.IsFocused) return;

        var lb = frameworkElement as ListBox;
        if (lb == null) return;

        lb.PreviewMouseWheel += LbOnPreviewMouseWheel;
    }

    private static void LbOnPreviewMouseWheel(object sender, MouseWheelEventArgs e)
    {
        if (!(sender is ListBox) || e.Handled) return;

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

        var parent = ((Control)sender).Parent as UIElement;
        if (parent != null) parent.RaiseEvent(eventArg);
    }
}

然后在你的XAML中,只需将以下内容放入列表框中:

 <ListBox extensions:ListboxExtensions.IgnoreScroll="True">

当然,在XAML的顶部记得包含你的扩展命名空间:
xmlns:extensions="clr-namespace:UI.Extensions"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接