WPF StackPanel "跳跃"问题

4

我有一个包含文本框和组合框的StackPanel。

当我将焦点设置在文本框内(不是第一个文本框),StackPanel的内容会“跳动”并回到顶部。

以下是代码。我已经研究过这个问题并尝试了找到的解决方法(但没有成功)。

我想要防止“跳动”发生。

请运行下面的代码。 滚动垂直滚动条,直到看到:

Name Three       <<Text Box
(No Selection) ComboBox \/
Name Four      <<Text Box
(No Selection) ComboBox \/

现在把光标放在“Name Four”文本框里......然后它会“跳”到顶部。 (现在你看不到 Three 和 Four,你看到的是 Four 和 Five。)

我的 StackPanel 在实际使用中比这个复杂得多,这让我的最终用户感到疯狂。

谢谢。

MainWindow.xaml

<Window x:Class="ListBoxControlSample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="160" Width="250">
    <Grid Margin="10">
        <ListBox ItemsSource="{Binding Models}" SelectionMode="Single" RequestBringIntoView="FrameworkElement_OnRequestBringIntoView" SelectionChanged="Selector_OnSelectionChanged" >
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel>
                        <TextBox Text="{Binding Name}"/>
                        <ComboBox VerticalContentAlignment="Top" VerticalAlignment="Top" Grid.Column="1" ItemsSource="{Binding Options}" >
                        </ComboBox>
                        <TextBlock Text="{Binding Title}"></TextBlock>
                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </Grid>
</Window>

MainWindow.xaml.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace ListBoxControlSample
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            DataContext = this;
        }

        private IList<Model> _models;
        public IList<Model> Models
        {
            get
            {
                return _models ?? (_models = new List<Model>
                    {
                        new Model{ Name = "Name One", Title = "Title One"},
                        new Model{ Name = "Name Two", Title = "Title Two"},
                        new Model{ Name = "Name Three", Title = "Title Three"},
                        new Model{ Name = "Name Four", Title = "Title Four"},
                        new Model{ Name = "Name Five", Title = "Title Five"},
                        new Model{ Name = "Name Six", Title = "Title Six"},
                        new Model{ Name = "Name Seven", Title = "Title Seven"}
                    });
            }
        }

        private void FrameworkElement_OnRequestBringIntoView(object sender, RequestBringIntoViewEventArgs e)
        {
            e.Handled = true;
        }

        private void Selector_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            //throw new NotImplementedException();
        }

        private void Selector_OnSelected(object sender, RoutedEventArgs e)
        {
            //throw new NotImplementedException();
        }
    }

    public class Model
    {
        public string Name { get; set; }
        public string Title { get; set; }
        private IList<string> _options;
        public IList<string> Options
        {
            get
            {
                return _options ?? (_options = new List<string>
                    {
                        "left",
                        "right",
                        "both"
                    });
            }
        }
    }
}

我发现并尝试过的方法(以防止跳跃)
        <DataTemplate>
                    <StackPanel ScrollViewer.CanContentScroll="False">

PS 我的WPF技能只是基本水平,几乎所有人都不在这周。:( - granadaCoder
如果您在发布问题后想添加一些内容,可以编辑您的问题;不需要在自己的问题上发表与其他评论无关的评论。(尽管针对特定评论而言,这两个陈述都不太可能增加您获得有用答案的机会;-)) - O. R. Mapper
6个回答

4
我猜这可能与默认的滚动行为有关,当选择项时尝试显示完整的项目。

尝试禁用滚动并将其包裹在另一个ScrollViewer中:

<ScrollViewer VerticalScrollBarVisibility="Auto" CanContentScroll="True" Height="250">
    <ListBox ScrollViewer.VerticalScrollBarVisibility="Disabled">
        ...
    </ListBox>
</ScrollViewer>

这种方式不是尝试一次性滚动每个StackPanel并确保完整项可见,而是尝试滚动整个ListBox以使其超出ScrollViewer分配的高度,因此它将使用您想要的更平滑的基于内容的滚动。
需要注意的是,这将一次性呈现整个ListBox,没有任何虚拟化,因此如果您有很多行并且依赖虚拟化进行性能优化,则不建议使用此方法。但根据您的问题,似乎不是这种情况。
我也不确定,但您可能还需要嵌套一个面板,以允许ListBox增长到所需的任何高度。如有必要,请参见此答案获取更多详细信息。

1
你救了除夕之夜!(我和我的团队在年底前有一个P1错误需要修复。)!!谢谢! - granadaCoder

4

这里有另一个答案。它适用于简单的WPF。

然而,我的实际情况中有一个Infragistics控件,Rachel的答案起作用了。

但是,我想为完整性贴出这个代码。

我将从此网址粘贴代码:

http://social.msdn.microsoft.com/Forums/vstudio/en-US/a3532b1f-d76e-4955-b3da-84c98d6d435c/annoying-auto-scroll-of-partially-displayed-items-in-wpf-listbox?forum=wpf

这是代码:

  <ListBox.ItemContainerStyle>
            <Style TargetType="ListBoxItem">
                <EventSetter Event="RequestBringIntoView" Handler="ListBoxItem_RequestBringIntoView"/>
            </Style>
        </ListBox.ItemContainerStyle>

并且

  void ListBoxItem_RequestBringIntoView(object sender, RequestBringIntoViewEventArgs e)
        {
            e.Handled = true;
        }

0
使用这个:
<ListBox ScrollViewer.PanningMode="None">

0

这个问题是由于ScrollVewier中的子项获得焦点并随后滚动到视图中引起的(在这种情况下,子元素是ListBoxItem)。

如果接收焦点的元素不需要通过Tab键进行导航,则一个简单的解决方案是通过Focusable=False使元素无法获得焦点。如果元素没有获得焦点,滚动视图器也不会尝试将其滚动到视图中。

在这种情况下,这可能是一个可接受的解决方案,因为我认为ListBoxItem更像是一个容器,而不是用户需要选择的控件。


0
如果您单击最后一个可见行的文本框,则可以复制效果。 如果该行没有完全滚动到视图中,列表框会自动滚动该行以使其完全可见。 这反过来又意味着所有行向上滚动一行,这会导致跳跃效果。 据我所知,您无法更改该行为。

0

当像SetFocus这样的命令在scrollviewer的子级上运行时,它会触发scrrollviewer上的ReqestBringInto view,但滚动到子控件的操作是由scrollviewer的ScrollInfo对象在幕后实现的。

我认为关键在于创建一个实现IScrollInfo的类。我实现了一个来覆盖使用鼠标滚轮时SV滚动的数量。在我的情况下,我从.NET源代码中的ScrollContentProvider克隆了默认实现,并更改了一些属性。

在内部,ScrollViewer将在所需的子控件上调用IScrollInfo :: MakeVisible()。您可以忽略该请求。

使用类似以下内容的东西为scrollviewer创建自己的滚动提供程序的实例:

var myProvider = new MyScrollInfo();
myScrollViewer.ScrollInfo = myProvider;

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