WPF Scroll&重点改变问题

时间:2011-05-10 10:40:20

标签: wpf wpf-controls scroll focus

我在滚动WPF应用程序时出现问题。

这是合约。我的用户界面如下:

ScrollViewer

我的应用程序的作用是充当许多应用程序的中心枢纽并启动它们。管理员可以启动另一个用户记录的转储。 因此,我有一个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列表的列表。我试图设置Focusable&amp; CanContentScrollFalse到处看似合适,但控件一直阻止主UI滚动......

我想我应该改变另一个属性......任何想法?

谢谢!

2 个答案:

答案 0 :(得分:1)

问题在于ListBox,或更具体地说,是ScrollViewer模板中的ListBox。这是获取滚动事件并在ScrollViewer中的外ListView甚至看到它们之前使用它们。

如果可能的话,我建议用ListBox替换ItemsControl。但是,这意味着不会有SelectedItem属性。如果您需要,我建议您将ScrollViewer.HorizontalScrollBarVisibility(或VerticalScrollBarVisibility)设置为Disabled。如果做不到这一点,我只能建议重新模板ListBox根本不包含ScrollViewer

答案 1 :(得分:1)

我遇到了一个列表框在滚动查看器中窃取焦点的问题(我在scrollviewer中有多个列表框)。所以我创建了一个附加属性,它拒绝列表框滚动的能力。因此,容纳列表框的滚动查看器可以滚动

您的控件是一个列表框,因此这应该按原样运行,但没有理由将扩展名限制为列表框;它只是为了符合我的确切目的。

 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"