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



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

所以当没有选择项目时,我想滚动到第一个项目。为此,我尝试了以下修复方法。

代码

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。控件。扩展让我可以选择获取滚动查看器,然后尝试ChangeView方法,但这不起作用。我成功地从列表中获得了第一个项目,并使用了ContainerFromItem方法,但它返回了null。因此,我还尝试了ContainerFromIndex方法,并将索引提供为0,因为这应该是第一项,但也不起作用。

在所选项(else语句(的情况下,它在ContainerFromIndex(comboBox.SelectedIndex)中运行良好,但只是为了测试当我使用ContainerFromItem时,它返回了null。

仅供参考,此事件是组合框样式的附加行为,但这并不重要,因为行为器在所选项目场景中完美工作。

如果您想在没有选定项目的情况下滚动到第一个项目,则需要更改ComboBoxDropDown而不是ComboBoxScrollViewer的行为。

ComboBoxDropDown实际上是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="&#xE0E5;" 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来设置DropDownStyle中的起始位置,但我们有一个变通方法,可以在DropDown中获取ScrollViewer,然后调用ChangeView方法来更改位置。例如:

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

请注意,在XAML中使用TestComboBox而不是ComboBox

相关内容

  • 没有找到相关文章

最新更新