如果您想在没有选中项时滚动到第一项,则需要更改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。