UWP组合框项目无缘无故地滚动到中间

问题描述

我注意到在一个附加了某些项目源的组合框中,当没有选定的项目时,它倾向于滚动到项目的中间,而不是从顶部(第一个项目)开始,并且在选择一个项目时有时滚动到所选项目。

因此,我想在未选择任何项目时滚动到第一项。为此,我尝试了以下修复程序。

代码

    private void ComboBoxKeyboardSelectionBehavior_DropDownOpened(object sender,object e)
    {
        var comboBox = (ComboBox) sender;
        if(comboBox.SelectedIndex == -1)
        {
            //var scrollviewer = comboBox.GetScrollViewer();
            //scrollviewer.ChangeView(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 为我提供了获取scrollviewer的选项,然后尝试使用 ChangeView 方法,但该方法不起作用。我从列表中成功获取了第一项,并使用了 ContainerFromItem 方法,但它返回了null。因此,我还尝试了 ContainerFromIndex 方法,并将索引提供为 0 ,因为这应该是第一项,但还是可行的。

对于选中的项目(其他语句),它可以与ContainerFromIndex(comboBox.SelectedIndex)一起正常工作,但是只是为了测试我何时使用 ContainerFromItem 尝试它返回空值。

仅供参考,此事件是组合框样式的附属行为,但这无关紧要,因为行为对于所选项目场景而言是完美的。

解决方法

如果要在没有选定项目的情况下滚动到第一项,则需要更改DropDown的{​​{1}}而不是{{ 1}}。

ComboBox的{​​{1}}实际上是ScrollViewer,显示ComboBox的位置在后面的代码中已定义,我们无法访问对此。一种解决方法是找到DropDown并在打开时重新放置它,但是使用此方法时,每次打开ComboBox属性时我们都需要计算它,并且存在很多不同的值的方案Popup

因此,我们建议您自定义一个控件,该控件的行为类似于Popup,并且在未选择任何项目的情况下将其定位到第一项。例如:

创建一个Popup

VerticalOffset

以及此UserControl中的代码:

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="&#xE0E5;" HorizontalAlignment="Right" Margin="0,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> 将在其下面显示其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的起始位置的相关API,但是我们有一种解决方法可以将ComboBox放入其中ComboBox,然后调用DropDown方法来更改位置。例如:

  1. 定义从Style类继承的自定义组合框以获取ScrollViewer
DropDown
  1. ChangeView事件处理程序中使用ComboBox初始化项目后,调用ScrollViewer方法来更改位置:
    public class TestComboBox : ComboBox
    {
        public ScrollViewer InternalScrollViewer;
        protected override void OnApplyTemplate()
        {
            InternalScrollViewer = GetTemplateChild("ScrollViewer") as ScrollViewer;
            base.OnApplyTemplate();
        }
    }

请注意,在 XAML 中使用ChangeView代替Task.Delay()

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...