UWP Combobox 项目无缘无故滚动到中间
Posted
技术标签:
【中文标题】UWP Combobox 项目无缘无故滚动到中间【英文标题】:UWP Combobox items scrolls to mid for no reason 【发布时间】:2021-01-31 05:49:51 【问题描述】:我注意到,在一个附加了一些 itemsource 的组合框中,当没有选定的项目时,它倾向于滚动到项目的中间而不是从顶部(第一个项目)开始,当一个项目被选中时它会滚动有时滚动到所选项目。
所以我想在没有选择任何项目时滚动到第一个项目。为此,我尝试了以下修复。
代码
private void ComboBoxKeyboardSelectionBehavior_DropDownOpened(object sender, object e)
var comboBox = (ComboBox) sender;
if(comboBox.SelectedIndex == -1)
//var scrollviewer = comboBox.GetScrollViewer();
//scrollviewer.ChangeView(0, 0, null);
//var allItems = comboBox.Items.ToList();
//var cccc = comboBox.Items.Count;
//var firstItem = allItems.First();
var ci = comboBox.ContainerFromIndex(0) as ComboBoxItem;
if (ci != null)
ci.StartBringIntoView();
else
var ci = comboBox.ContainerFromIndex(comboBox.SelectedIndex) as ComboBoxItem;
if (ci != null)
ci.StartBringIntoView();
WinRTXamlToolkit.Controls.Extensions 为我提供了获取滚动查看器的选项,然后尝试使用 ChangeView 方法,但这不起作用。我成功地从列表中获得了第一项并使用了 ContainerFromItem 方法,但它返回了 null。所以我也尝试了 ContainerFromIndex 方法并将索引提供为 0 因为这应该是第一项,但它也不起作用。
如果是选定的项目(else 语句),它与ContainerFromIndex(comboBox.SelectedIndex)
一起工作正常,但只是为了测试当我用 ContainerFromItem 尝试它时它返回 null。
仅供参考,此事件是组合框样式的附加行为,但这无关紧要,因为行为在选定项目场景中完美运行。
【问题讨论】:
【参考方案1】:如果您想在没有选中项时滚动到第一项,则需要更改ComboBox
的DropDown
的行为而不是ScrollViewer
的ComboBox
。
ComboBox
的DropDown
实际上是Popup
,而Popup
的显示位置在后面的代码中定义,我们无法访问。一种解决方法是找到Popup
并在打开时重新定位它,但是使用这种方法我们需要在每次打开时计算VerticalOffset
属性,并且VerticalOffset
的不同值有很多场景。
因此,我们建议您自定义一个控件,其行为类似于ComboBox
,并且在未选择任何项目时定位到第一个项目。例如:
创建UserControl
:
<Button x:Name="rootButton" BorderBrush="Gray" BorderThickness="2" Click="Button_Click" MinWidth="80" Background="Transparent" Padding="0">
<Grid VerticalAlignment="Stretch" HorizontalAlignment="Stretch"
Width="Binding ElementName=rootButton, Path=ActualWidth">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="32" />
</Grid.ColumnDefinitions>
<TextBlock Text="x:Bind selectedItem, Mode=OneWay" Grid.Column="0" VerticalAlignment="Center" FontSize="15" HorizontalAlignment="Center" />
<FontIcon Grid.Column="1" FontSize="12" FontFamily="Segoe MDL2 Assets" Glyph="" HorizontalAlignment="Right"
Margin="0,10,10,10" VerticalAlignment="Center" />
</Grid>
<FlyoutBase.AttachedFlyout>
<MenuFlyout Placement="Bottom" x:Name="menuFlyout">
<MenuFlyoutItem Text="Item 1" Click="MenuFlyoutItem_Click" />
<MenuFlyoutItem Text="Item 2" Click="MenuFlyoutItem_Click" />
<MenuFlyoutItem Text="Item 3" Click="MenuFlyoutItem_Click" />
<MenuFlyoutItem Text="Item 4" Click="MenuFlyoutItem_Click" />
<MenuFlyoutItem Text="Item 5" Click="MenuFlyoutItem_Click" />
</MenuFlyout>
</FlyoutBase.AttachedFlyout>
还有这个 UserControl 后面的代码:
public sealed partial class CustomComboBox : UserControl, INotifyPropertyChanged
public CustomComboBox()
this.InitializeComponent();
selectedItem = "";
private string _selectedItem;
public string selectedItem
get return _selectedItem;
set
_selectedItem = value;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("selectedItem"));
public event PropertyChangedEventHandler PropertyChanged;
private void MenuFlyoutItem_Click(object sender, RoutedEventArgs e)
var item = sender as MenuFlyoutItem;
selectedItem = item.Text;
private void Button_Click(object sender, RoutedEventArgs e)
FlyoutBase.ShowAttachedFlyout(sender as Button);
您可以像这样在其他页面中使用CustomComboBox
:
<local:CustomComboBox VerticalAlignment="Center" HorizontalAlignment="Center" />
默认情况下,此CustomComboBox
将在其下方显示其DropDown
列表。
此外,您还可以考虑使用ListBox
等其他控件直接替换ComboBox
来避免这种情况。
更新:
目前ComboBox
控件并没有提供相关的API来设置DropDown
在Style
中的起始位置,但是我们有一个变通方法是在DropDown
中获取ScrollViewer
,然后调用ChangeView
方法来改变位置。例如:
-
定义一个继承自
ComboBox
类的自定义组合框以获取ScrollViewer
:
public class TestComboBox : ComboBox
public ScrollViewer InternalScrollViewer;
protected override void OnApplyTemplate()
InternalScrollViewer = GetTemplateChild("ScrollViewer") as ScrollViewer;
base.OnApplyTemplate();
-
在
ComboBoxKeyboardSelectionBehavior_DropDownOpened
事件处理程序中使用Task.Delay()
初始化项目后,调用ChangeView
方法改变位置:
await Task.Delay(50);
comboBox.InternalScrollViewer.ChangeView(0, 0, 1);
注意,在 XAML 中使用 TestComboBox
而不是 ComboBox
。
【讨论】:
您的问题解决了吗?如果还没有解决,请随时联系我们。 我希望在样式和行为中找到一个解决方案,这样我们就不需要制作自定义控件,因为我们有大量的组合框,并且制作自定义控件可能不是我们场景的最佳主意。 我们已经有了组合框的样式,我们在 xaml 中做了大量的自定义内容以及一些附加到它的行为。 我更新了答案,您可以检查一下新的解决方法是否可以解决您的问题。以上是关于UWP Combobox 项目无缘无故滚动到中间的主要内容,如果未能解决你的问题,请参考以下文章
c# UWP TreeView 在 ItemDrag 上自动滚动