我有一个包含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">
答案 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的答案有效。
但是,我想发布此内容以确保完整性。
我正在粘贴此网址的代码:
以下是代码:
<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的作用不仅仅是充当容器,而不仅仅是用户需要选择的控件。