WPF StackPanel“跳跃”

时间:2013-12-30 15:39:28

标签: c# wpf xaml

我有一个包含TextBox和Combobox的StackPanel。

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

以下是代码。我研究了这个并发布了我发现并试过的那个(但没有工作)。

我想阻止“跳跃”。

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

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

现在将光标放在“Name Four”文本框中.......并将其“跳转”到顶部。 (你现在看不到三和四,你看到四和五。)

我的堆叠面板在现实生活中比这复杂得多,并且它驱使我的最终用户疯狂。

感谢。

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">

6 个答案:

答案 0 :(得分:1)

我猜这与尝试在选中时显示完整项目的默认滚动行为有关。

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

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

这样,您可以尝试将整个StackPanel滚动到视图中,而不是尝试将每个ListBox一次滚动到视图中,而不是尝试将整个项ScrollViewer滚动到视图中高度分配给ListBox,因此它将使用您想要的更平滑的基于内容的滚动。

应该注意的是,这将立即呈现整个{{1}},没有任何虚拟化,因此如果您有大量行并且依赖于虚拟化以提高性能,则不建议使用此方法。但根据你的问题,这听起来不是你的情况。

我也不是正面的,但你可能还需要将它嵌套在另一个面板中,以允许ListBox增长到它想要的任何高度。如果需要,请参阅this answer了解更多详情。

答案 1 :(得分:1)

这是另一个答案。它适用于简单的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;
        }

答案 2 :(得分:0)

如果单击最后一个可见行的TextBox,则效果可重现。如果该行未完全滚动到视图中,则列表框会自动将该行滚动到视图中以使其完全可见。这反过来意味着所有行向上滚动一行,让您感受到跳跃效果。据我所知,你无法改变这种行为。

答案 3 :(得分:0)

当像SetFocus这样的命令在scrollviewer的子节点上运行时,它会在scrrollviewer上触发ReqestBringInto视图,但滚动到子控件的行为是由scrollviewer的ScrollInfo对象实现的。

我认为这里的关键是创建一个实现IScrollInfo的类。我实现了一个来覆盖使用鼠标滚轮时SV滚动的数量。就我而言,我克隆了.NET source for ScrollContentProvider中的默认实现,并更改了一些属性。

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

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

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

答案 4 :(得分:0)

使用此:

<ListBox ScrollViewer.PanningMode="None">

答案 5 :(得分:0)

ScrollVewier中的子项获得焦点并随后滚动到视图中时(在这种情况下,子元素为ListBoxItem),将导致此问题。

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

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