简体   繁体   English

带下拉框的自动填充框

[英]Auto-complete box with drop-down

The AutoCompleteBox is pretty great, but one feature it lacks is a click-to-drop-down all the available options. AutoCompleteBox非常好,但是它缺少的一个功能是单击下拉所有可用选项。 You can come close by setting MinimumPrefixLength =0 -- that way, the user can get the complete drop-down list by deleting the text. 您可以通过设置MinimumPrefixLength = 0接近-这样,用户可以通过删除文本来获得完整的下拉列表。 This has a couple of limitations, though: 但是,这有两个限制:

  • if there is no text to begin with, then the user would have to enter some text and delete it (non-intuitive and inconvenient) 如果没有开头的文本,则用户将不得不输入一些文本并将其删除(不直观且不方便)
  • the click-and-keypress sequence seems like suboptimal UX. 单击和按键顺序似乎是次优的UX。

How would you tweak this control to make it drop down the complete list of options, when the user clicks on the control (or, also fine, a button to the right)? 当用户单击控件时(或者也可以单击右侧的按钮),您将如何调整该控件以使其落入选项的完整列表?


It seems I have disappointed @HighCore. 看来我对@HighCore感到失望。 So far I tried adding a button to the control template, which triggers opening the Popup. 到目前为止,我尝试将按钮添加到控件模板,这将触发打开弹出窗口。 The drawback to this approach is that, if there is text entered, then the list will be filtered per the normal filtering rules. 这种方法的缺点是,如果输入了文本,则将按照常规过滤规则过滤列表。 Now, you could clear the text, thus removing the filter, but this has another side effect: de-selecting the currently selected item (in contrast to a ComboBox, whose drop-down you can open without de-selecting). 现在,您可以清除文本,从而删除过滤器,但这还有另一个副作用:取消选择当前选定的项目(与ComboBox相对,您可以打开其下拉菜单而无需取消选择)。 So ... what now? 所以现在怎么办? Temporarily remove the filter, and restore it when the popup is closed or the user types anything else? 临时删除过滤器,并在关闭弹出窗口或用户键入其他任何内容时恢复过滤器?

I built a control like that, the approach I used was to inherit from the AutoComboBox control and remove the filter when the dropdown opens. 我建立了这样的控件,我使用的方法是从AutoComboBox控件继承并在下拉列表打开时删除过滤器。

EDIT Code has been updated to include missing resources. 编辑代码已更新,以包括缺少的资源。

Code is: 代码是:

public class AutoCompleteComboBox : AutoCompleteBox
{
    /// <summary>
    /// Occurs when drop down toggle button is clicked.
    /// </summary>
    public event EventHandler ToggleButtonClick;

    private object _holdSelectedItem;
    private AutoCompleteFilterMode _holdFilterMode;

    /// <summary>
    /// Identifies the DisplayMemberPath dependency property.
    /// </summary>
    public static readonly DependencyProperty DisplayMemberPathProperty = DependencyProperty.Register("DisplayMemberPath", typeof(string), typeof(AutoCompleteComboBox), new PropertyMetadata(string.Empty, DisplayMemberPath_PropertyChanged));
    /// <summary>
    /// Gets or sets the name or path of the property 
    /// that is displayed for each the data item in the control.
    /// </summary>
    public string DisplayMemberPath
    {
        get { return (string)GetValue(DisplayMemberPathProperty); }
        set { SetValue(DisplayMemberPathProperty, value); }
    }
    private static void DisplayMemberPath_PropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var accb = (AutoCompleteComboBox)d;
        accb.ValueMemberPath = e.NewValue.ToString();
    }

    /// <summary>
    /// Identifies the MaxLength dependency property.
    /// </summary>
    public static readonly DependencyProperty MaxLengthProperty = DependencyProperty.Register("MaxLength", typeof(int), typeof(AutoCompleteComboBox), null);
    /// <summary>
    /// Gets or sets the maximum number of characters allowed for user input.
    /// </summary>
    public int MaxLength
    {
        get { return (int)GetValue(MaxLengthProperty); }
        set { SetValue(MaxLengthProperty, value); }
    }

    /// <summary>
    /// Gets or sets a collection used to generate the content of the control.
    /// </summary>
    public new IEnumerable ItemsSource
    {
        get { return GetValue(ItemsSourceProperty) as IEnumerable; }
        set
        {
            SetValue(SelectedItemProperty, null);
            SetValue(ItemsSourceProperty, value);
            Dispatcher.BeginInvoke(() => SetValue(TextProperty, string.Empty));
            _holdSelectedItem = null;
        }
    }

    /// <summary>
    /// Initializes a new instance of the AutoCompleteComboBox control.
    /// </summary>
    public AutoCompleteComboBox()
    {
        StreamResourceInfo sri = Application.GetResourceStream(new Uri("/UI.Controls;component/AutoCompleteComboBox.xaml", UriKind.Relative));
        var sr = new StreamReader(sri.Stream);
        Style = (Style)XamlReader.Load(sr.ReadToEnd());

        DropDownClosed += AutoCompleteComboBox_DropDownClosed;
        DropDownOpened += AutoCompleteComboBox_DropDownOpened;
    }

    /// <summary>
    /// Called when the template's tree is generated.
    /// </summary>
    public override void OnApplyTemplate()
    {
        base.OnApplyTemplate();

        var toggle = (ToggleButton)GetTemplateChild("PopupToggleButton");
        toggle.Click += DropDownToggle_Click;

        var lb = (ListBox)GetTemplateChild("Selector");
        lb.DisplayMemberPath = DisplayMemberPath;
        _holdFilterMode = FilterMode;

        TextChanged += AutoCompleteComboBox_TextChanged;
        SelectionChanged += new SelectionChangedEventHandler(AutoCompleteComboBox_SelectionChanged);
    }

    private void AutoCompleteComboBox_DropDownClosed(object sender, RoutedPropertyChangedEventArgs<bool> e)
    {
        if (SelectedItem == null && _holdSelectedItem != null && SelectedItem != _holdSelectedItem && ItemsSource.Cast<object>().Contains(_holdSelectedItem))
        {
            SelectedItem = _holdSelectedItem;
        }
        _holdSelectedItem = null;
        FilterMode = _holdFilterMode;
    }

    private void AutoCompleteComboBox_DropDownOpened(object sender, RoutedPropertyChangedEventArgs<bool> e)
    {
        var lb = (ListBox)GetTemplateChild("Selector");
        ScrollViewer sv = lb.GetScrollHost();
        if (sv != null)
        {
            sv.ScrollToTop();
        }
        if (SelectedItem != null)
        {
            lb.SelectedItem = SelectedItem;
            _holdSelectedItem = SelectedItem;
        }
    }

    private void DropDownToggle_Click(object sender, RoutedEventArgs e)
    {
        IsDropDownOpen = !IsDropDownOpen;
        if (ToggleButtonClick != null)
        {
            ToggleButtonClick(this, e);
        }
        if (IsDropDownOpen)
        {
            _holdFilterMode = FilterMode;
            FilterMode = AutoCompleteFilterMode.None;
            ((TextBox)GetTemplateChild("Text")).SelectAll();
        }
        Focus();
    }

    private void AutoCompleteComboBox_TextChanged(object sender, RoutedEventArgs e)
    {
        if (IsDropDownOpen)
        {
            if (FilterMode == AutoCompleteFilterMode.None && FilterMode != _holdFilterMode)
            {
                FilterMode = _holdFilterMode;
            }
            ScrollViewer sv = ((ListBox)GetTemplateChild("Selector")).GetScrollHost();
            if (sv != null)
            {
                sv.ScrollToTop();
            }
        }
    }

    private void AutoCompleteComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        if (!IsDropDownOpen && SelectedItem == null)
        {
            Text = string.Empty;
        }
    }
}

<Setter Property="Height" Value="24" />
<Setter Property="MinimumPopulateDelay" Value="1" />
<Setter Property="IsTextCompletionEnabled" Value="False" />
<Setter Property="MinimumPrefixLength" Value="0" />
<Setter Property="MaxDropDownHeight" Value="300" />
<Setter Property="IsTabStop" Value="False" />
<Setter Property="Padding" Value="2" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="BorderBrush" Value="#FF000000" />
<Setter Property="Background" Value="#FFFFFFFF" />
<Setter Property="Foreground" Value="#FF000000" />
<Setter Property="MinWidth" Value="45" />
<Setter Property="FilterMode" Value="Contains" />
<Setter Property="Template">
    <Setter.Value>
        <ControlTemplate TargetType="ctrls:AutoCompleteComboBox">
            <Grid >
                <Grid.Resources>
                    <Style x:Name="comboToggleStyle" TargetType="ToggleButton">
                        <Setter Property="Foreground" Value="#FF333333"/>
                        <Setter Property="Background" Value="#FF1F3B53"/>
                        <Setter Property="BorderBrush">
                            <Setter.Value>
                                <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                                    <GradientStop Color="#FFA3AEB9" Offset="0"/>
                                    <GradientStop Color="#FF8399A9" Offset="0.375"/>
                                    <GradientStop Color="#FF718597" Offset="0.375"/>
                                    <GradientStop Color="#FF617584" Offset="1"/>
                                </LinearGradientBrush>
                            </Setter.Value>
                        </Setter>
                        <Setter Property="BorderThickness" Value="1"/>
                        <Setter Property="Padding" Value="3"/>
                        <Setter Property="Template">
                            <Setter.Value>
                                <ControlTemplate TargetType="ToggleButton">
                                    <Grid>
                                        <VisualStateManager.VisualStateGroups>
                                            <VisualStateGroup x:Name="CommonStates">
                                                <VisualState x:Name="Normal"/>
                                                <VisualState x:Name="MouseOver">
                                                    <Storyboard>
                                                        <DoubleAnimation Duration="0" Storyboard.TargetName="BackgroundOverlay" Storyboard.TargetProperty="Opacity" To="1"/>
                                                        <ColorAnimation Duration="0" Storyboard.TargetName="BackgroundGradient" Storyboard.TargetProperty="(Shape.Fill).(GradientBrush.GradientStops)[3].(GradientStop.Color)" To="#7FFFFFFF"/>
                                                        <ColorAnimation Duration="0" Storyboard.TargetName="BackgroundGradient" Storyboard.TargetProperty="(Shape.Fill).(GradientBrush.GradientStops)[2].(GradientStop.Color)" To="#CCFFFFFF"/>
                                                        <ColorAnimation Duration="0" Storyboard.TargetName="BackgroundGradient" Storyboard.TargetProperty="(Shape.Fill).(GradientBrush.GradientStops)[1].(GradientStop.Color)" To="#F2FFFFFF"/>
                                                    </Storyboard>
                                                </VisualState>
                                                <VisualState x:Name="Pressed">
                                                    <Storyboard>
                                                        <DoubleAnimation Duration="0" Storyboard.TargetName="BackgroundOverlay2" Storyboard.TargetProperty="Opacity" To="1"/>
                                                        <DoubleAnimation Duration="0" Storyboard.TargetName="Highlight" Storyboard.TargetProperty="(UIElement.Opacity)" To="1"/>
                                                        <ColorAnimation Duration="0" Storyboard.TargetName="BackgroundGradient" Storyboard.TargetProperty="(Shape.Fill).(GradientBrush.GradientStops)[1].(GradientStop.Color)" To="#E5FFFFFF"/>
                                                        <ColorAnimation Duration="0" Storyboard.TargetName="BackgroundGradient" Storyboard.TargetProperty="(Shape.Fill).(GradientBrush.GradientStops)[2].(GradientStop.Color)" To="#BCFFFFFF"/>
                                                        <ColorAnimation Duration="0" Storyboard.TargetName="BackgroundGradient" Storyboard.TargetProperty="(Shape.Fill).(GradientBrush.GradientStops)[3].(GradientStop.Color)" To="#6BFFFFFF"/>
                                                        <ColorAnimation Duration="0" Storyboard.TargetName="BackgroundGradient" Storyboard.TargetProperty="(Shape.Fill).(GradientBrush.GradientStops)[0].(GradientStop.Color)" To="#F2FFFFFF"/>
                                                    </Storyboard>
                                                </VisualState>
                                                <VisualState x:Name="Disabled" />
                                            </VisualStateGroup>
                                            <VisualStateGroup x:Name="CheckStates">
                                                <VisualState x:Name="Checked">
                                                    <Storyboard>
                                                        <DoubleAnimation Duration="0" Storyboard.TargetName="BackgroundOverlay3" Storyboard.TargetProperty="(UIElement.Opacity)" To="1"/>
                                                        <DoubleAnimation Duration="0" Storyboard.TargetName="Highlight" Storyboard.TargetProperty="(UIElement.Opacity)" To="1"/>
                                                        <DoubleAnimation Duration="0" Storyboard.TargetName="BackgroundGradient2" Storyboard.TargetProperty="(UIElement.Opacity)" To="1"/>
                                                        <ColorAnimation Duration="0" Storyboard.TargetName="BackgroundGradient2" Storyboard.TargetProperty="(Shape.Fill).(GradientBrush.GradientStops)[1].(GradientStop.Color)" To="#E5FFFFFF"/>
                                                        <ColorAnimation Duration="0" Storyboard.TargetName="BackgroundGradient2" Storyboard.TargetProperty="(Shape.Fill).(GradientBrush.GradientStops)[2].(GradientStop.Color)" To="#BCFFFFFF"/>
                                                        <ColorAnimation Duration="0" Storyboard.TargetName="BackgroundGradient2" Storyboard.TargetProperty="(Shape.Fill).(GradientBrush.GradientStops)[3].(GradientStop.Color)" To="#6BFFFFFF"/>
                                                        <ColorAnimation Duration="0" Storyboard.TargetName="BackgroundGradient2" Storyboard.TargetProperty="(Shape.Fill).(GradientBrush.GradientStops)[0].(GradientStop.Color)" To="#F2FFFFFF"/>
                                                    </Storyboard>
                                                </VisualState>
                                                <VisualState x:Name="Unchecked"/>
                                            </VisualStateGroup>
                                            <VisualStateGroup x:Name="FocusStates">
                                                <VisualState x:Name="Focused">
                                                    <Storyboard>
                                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="FocusVisualElement" Storyboard.TargetProperty="Visibility" Duration="0">
                                                            <DiscreteObjectKeyFrame KeyTime="0">
                                                                <DiscreteObjectKeyFrame.Value>
                                                                    <Visibility>Visible</Visibility>
                                                                </DiscreteObjectKeyFrame.Value>
                                                            </DiscreteObjectKeyFrame>
                                                        </ObjectAnimationUsingKeyFrames>
                                                    </Storyboard>
                                                </VisualState>
                                                <VisualState x:Name="Unfocused" />
                                            </VisualStateGroup>
                                        </VisualStateManager.VisualStateGroups>
                                        <Rectangle x:Name="Background" RadiusX="3" RadiusY="3" Fill="{TemplateBinding Background}" StrokeThickness="{TemplateBinding BorderThickness}" Stroke="{TemplateBinding BorderBrush}"/>
                                        <Rectangle x:Name="BackgroundOverlay" Opacity="0" RadiusX="3" RadiusY="3" Fill="#FF448DCA" StrokeThickness="{TemplateBinding BorderThickness}" Stroke="#00000000"/>
                                        <Rectangle x:Name="BackgroundOverlay2" Opacity="0" RadiusX="3" RadiusY="3" Fill="#FF448DCA" StrokeThickness="{TemplateBinding BorderThickness}" Stroke="#00000000"/>
                                        <Rectangle x:Name="BackgroundGradient" RadiusX="2" RadiusY="2" StrokeThickness="1" Margin="{TemplateBinding BorderThickness}" Stroke="#FFFFFFFF">
                                            <Rectangle.Fill>
                                                <LinearGradientBrush StartPoint=".7,0" EndPoint=".7,1">
                                                    <GradientStop Color="#FFFFFFFF" Offset="0" />
                                                    <GradientStop Color="#F9FFFFFF" Offset="0.375" />
                                                    <GradientStop Color="#E5FFFFFF" Offset="0.625" />
                                                    <GradientStop Color="#C6FFFFFF" Offset="1" />
                                                </LinearGradientBrush>
                                            </Rectangle.Fill>
                                        </Rectangle>
                                        <Rectangle Opacity="0" x:Name="BackgroundOverlay3" RadiusX="3" RadiusY="3" Fill="#FF448DCA" StrokeThickness="{TemplateBinding BorderThickness}" Stroke="#00000000"/>
                                        <Rectangle Opacity="0" x:Name="BackgroundGradient2" RadiusX="2" RadiusY="2" StrokeThickness="1" Margin="{TemplateBinding BorderThickness}" Stroke="#FFFFFFFF">
                                            <Rectangle.Fill>
                                                <LinearGradientBrush StartPoint=".7,0" EndPoint=".7,1">
                                                    <GradientStop Color="#FFFFFFFF" Offset="0" />
                                                    <GradientStop Color="#F9FFFFFF" Offset="0.375" />
                                                    <GradientStop Color="#E5FFFFFF" Offset="0.625" />
                                                    <GradientStop Color="#C6FFFFFF" Offset="1" />
                                                </LinearGradientBrush>
                                            </Rectangle.Fill>
                                        </Rectangle>
                                        <Rectangle x:Name="Highlight" RadiusX="2" RadiusY="2" Opacity="0" IsHitTestVisible="false" Stroke="#FF6DBDD1" StrokeThickness="1" Margin="{TemplateBinding BorderThickness}" />
                                        <ContentPresenter
                                                  x:Name="contentPresenter"
                                                  Content="{TemplateBinding Content}"
                                                  ContentTemplate="{TemplateBinding ContentTemplate}"
                                                  HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                                  VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                                                  Margin="{TemplateBinding Padding}"/>
                                        <Rectangle x:Name="FocusVisualElement" RadiusX="3.5" Margin="1"  RadiusY="3.5" Stroke="#FF6DBDD1" StrokeThickness="1" Visibility="Collapsed" IsHitTestVisible="false" />
                                    </Grid>
                                </ControlTemplate>
                            </Setter.Value>
                        </Setter>
                    </Style>

                    <ControlTemplate x:Key="CommonValidationToolTipTemplate" TargetType="ToolTip">
                        <Grid x:Name="Root" Margin="5,0" RenderTransformOrigin="0,0" Opacity="0">
                            <Grid.RenderTransform>
                                <TranslateTransform x:Name="Translation" X="-25" />
                            </Grid.RenderTransform>
                            <VisualStateManager.VisualStateGroups>
                                <VisualStateGroup Name="OpenStates">
                                    <VisualStateGroup.Transitions>
                                        <VisualTransition GeneratedDuration="0" />
                                        <VisualTransition To="Open" GeneratedDuration="0:0:0.2">
                                            <Storyboard>
                                                <DoubleAnimation Storyboard.TargetName="Translation" Storyboard.TargetProperty="X" To="0" Duration="0:0:0.2">
                                                    <DoubleAnimation.EasingFunction>
                                                        <BackEase Amplitude=".3" EasingMode="EaseOut" />
                                                    </DoubleAnimation.EasingFunction>
                                                </DoubleAnimation>
                                                <DoubleAnimation Storyboard.TargetName="Root" Storyboard.TargetProperty="Opacity" To="1" Duration="0:0:0.2" />
                                            </Storyboard>
                                        </VisualTransition>
                                    </VisualStateGroup.Transitions>
                                    <VisualState x:Name="Closed">
                                        <Storyboard>
                                            <DoubleAnimation Storyboard.TargetName="Root" Storyboard.TargetProperty="Opacity" To="0" Duration="0" />
                                        </Storyboard>
                                    </VisualState>
                                    <VisualState x:Name="Open">
                                        <Storyboard>
                                            <DoubleAnimation Storyboard.TargetName="Translation" Storyboard.TargetProperty="X" To="0" Duration="0" />
                                            <DoubleAnimation Storyboard.TargetName="Root" Storyboard.TargetProperty="Opacity" To="1" Duration="0" />
                                        </Storyboard>
                                    </VisualState>
                                </VisualStateGroup>
                            </VisualStateManager.VisualStateGroups>

                            <Border Margin="4,4,-4,-4" Background="#052A2E31" CornerRadius="5" />
                            <Border Margin="3,3,-3,-3" Background="#152A2E31" CornerRadius="4" />
                            <Border Margin="2,2,-2,-2" Background="#252A2E31" CornerRadius="3" />
                            <Border Margin="1,1,-1,-1" Background="#352A2E31" CornerRadius="2" />

                            <Border Background="#FFDC000C" CornerRadius="2">
                                <TextBlock UseLayoutRounding="false" Foreground="White" Margin="8,4,8,4" MaxWidth="250" TextWrapping="Wrap" Text="{Binding (Validation.Errors)[0].ErrorContent}" />
                            </Border>
                        </Grid>
                    </ControlTemplate>
                </Grid.Resources>
                <TextBox x:Name="Text" VerticalContentAlignment="Center" Background="{TemplateBinding Background}" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}" Foreground="{TemplateBinding Foreground}" MaxLength="{TemplateBinding MaxLength}" />
                <ToggleButton x:Name="PopupToggleButton" Width="24" HorizontalAlignment="Right" Style="{StaticResource comboToggleStyle}" Margin="1" >
                    <Path x:Name="BtnArrow" Height="4" Width="8" Stretch="Uniform" Data="F1 M 301.14,-189.041L 311.57,-189.041L 306.355,-182.942L 301.14,-189.041 Z " HorizontalAlignment="Center">
                        <Path.Fill>
                            <SolidColorBrush x:Name="BtnArrowColor" Color="#FF333333"/>
                        </Path.Fill>
                    </Path>
                </ToggleButton>
                <Border x:Name="ValidationErrorElement" Visibility="Collapsed" BorderBrush="#FFDB000C" BorderThickness="1" CornerRadius="1">
                    <ToolTipService.ToolTip>
                        <ToolTip x:Name="validationTooltip" DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}" Template="{StaticResource CommonValidationToolTipTemplate}" Placement="Right" PlacementTarget="{Binding RelativeSource={RelativeSource TemplatedParent}}">
                            <ToolTip.Triggers>
                                <EventTrigger RoutedEvent="Canvas.Loaded">
                                    <BeginStoryboard>
                                        <Storyboard>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="validationTooltip" Storyboard.TargetProperty="IsHitTestVisible">
                                                <DiscreteObjectKeyFrame KeyTime="0">
                                                    <DiscreteObjectKeyFrame.Value>
                                                        <system:Boolean>true</system:Boolean>
                                                    </DiscreteObjectKeyFrame.Value>
                                                </DiscreteObjectKeyFrame>
                                            </ObjectAnimationUsingKeyFrames>
                                        </Storyboard>
                                    </BeginStoryboard>
                                </EventTrigger>
                            </ToolTip.Triggers>
                        </ToolTip>
                    </ToolTipService.ToolTip>
                    <Grid Height="12" HorizontalAlignment="Right" Margin="1,-4,-4,0" VerticalAlignment="Top" Width="12" Background="Transparent">
                        <Path Fill="#FFDC000C" Margin="1,3,0,0" Data="M 1,0 L6,0 A 2,2 90 0 1 8,2 L8,7 z" />
                        <Path Fill="#ffffff" Margin="1,3,0,0" Data="M 0,0 L2,0 L 8,6 L8,8" />
                    </Grid>
                </Border>
                <Popup x:Name="Popup">
                    <ListBox x:Name="Selector" SelectionMode="Single" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Auto" MaxHeight="{TemplateBinding MaxDropDownHeight}" />
                </Popup>
                <VisualStateManager.VisualStateGroups>
                    <VisualStateGroup x:Name="PopupStates">
                        <VisualStateGroup.Transitions>
                            <VisualTransition GeneratedDuration="0:0:0" To="PopupOpened" />
                            <VisualTransition GeneratedDuration="0:0:0" To="PopupClosed" />
                        </VisualStateGroup.Transitions>
                        <VisualState x:Name="PopupOpened">
                        </VisualState>
                        <VisualState x:Name="PopupClosed">
                        </VisualState>
                    </VisualStateGroup>
                    <VisualStateGroup x:Name="ValidationStates">
                        <VisualState x:Name="Valid" />
                        <VisualState x:Name="InvalidUnfocused">
                            <Storyboard>
                                <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ValidationErrorElement" Storyboard.TargetProperty="Visibility">
                                    <DiscreteObjectKeyFrame KeyTime="0">
                                        <DiscreteObjectKeyFrame.Value>
                                            <Visibility>Visible</Visibility>
                                        </DiscreteObjectKeyFrame.Value>
                                    </DiscreteObjectKeyFrame>
                                </ObjectAnimationUsingKeyFrames>
                            </Storyboard>
                        </VisualState>
                        <VisualState x:Name="InvalidFocused">
                            <Storyboard>
                                <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ValidationErrorElement" Storyboard.TargetProperty="Visibility">
                                    <DiscreteObjectKeyFrame KeyTime="0">
                                        <DiscreteObjectKeyFrame.Value>
                                            <Visibility>Visible</Visibility>
                                        </DiscreteObjectKeyFrame.Value>
                                    </DiscreteObjectKeyFrame>
                                </ObjectAnimationUsingKeyFrames>
                                <ObjectAnimationUsingKeyFrames Storyboard.TargetName="validationTooltip" Storyboard.TargetProperty="IsOpen">
                                    <DiscreteObjectKeyFrame KeyTime="0">
                                        <DiscreteObjectKeyFrame.Value>
                                            <system:Boolean>True</system:Boolean>
                                        </DiscreteObjectKeyFrame.Value>
                                    </DiscreteObjectKeyFrame>
                                </ObjectAnimationUsingKeyFrames>
                            </Storyboard>
                        </VisualState>
                    </VisualStateGroup>
                </VisualStateManager.VisualStateGroups>
            </Grid>
        </ControlTemplate>
    </Setter.Value>
</Setter>

I worked out one approach. 我制定了一种方法。 The basic idea is to overlay a button, either in a modified control template, or just flung on top of the view (I'll use the latter here for brevity's sake). 基本思想是在修改后的控件模板中覆盖按钮,或者将其放在视图顶部(为简洁起见,在此使用后者)。 The button thing does three things: 按钮事物执行三件事:

  1. Clear the text (in order to restore the complete unfiltered list) 清除文本(以恢复完整的未过滤列表)
  2. Set IsDropDownOpen = true to open the Popup 设置IsDropDownOpen = true以打开弹出IsDropDownOpen
  3. Restore the selected item to the ListBox template child 将所选项目还原到ListBox模板子级

So basically, I have a setup like this: 所以基本上,我有这样的设置:

<Grid>
    <mycontrols:ExtendedAutoCompleteBox x:Name="autoCompleteBox" ... />
    <Button HorizontalAlignment="Right" Click="Button_Click">
        <Path Data="F1 M 301.14,-189.041L 311.57,-189.041L 306.355,-182.942L 301.14,-189.041 Z " 
              Fill="Black" Stretch="Uniform"
              Width="8" Height="4"
              />
    </Button>
</Grid>

The purpose of subclassing AutoCompleteBox is just to get access to the template child: 子类化AutoCompleteBox的目的仅仅是为了访问模板子级:

public class ExtendedAutoCompleteBox : AutoCompleteBox
{
    private ListBox _listBox;

    public override void OnApplyTemplate()
    {
        _listBox = GetTemplateChild("Selector") as ListBox;
    }

    public void ShowAllOptions()
    {
        var selectedItem = SelectedItem;
        Text = "";
        IsDropDownOpen = true;

        _listBox.SelectedItem = selectedItem;
        UpdateLayout();
        _listBox.ScrollIntoView(selectedItem);
    }
}

And so the button click will just call this "ShowAllOptions": 因此,单击按钮只会将其称为“ ShowAllOptions”:

private void Button_Click(object sender, RoutedEventArgs e)
{
    autoCompleteBox.ShowAllOptions();
}

It's not perfect -- for some reason the keyboard controls get screwy after clicking the button (if you press enter on an item, it does not select the item, but clears it instead) -- but it is better than nothing. 这不是完美的-出于某种原因,单击按钮后键盘控件会拧紧(如果在某个项目上按Enter,则它不会选择该项目,而是将其清除)-但总比没有好。

So just to illustrate what it does: let's say you have an item "x" selected, and you click the arrow button, then you will see the complete list: 因此,仅举例说明它的作用:假设您选择了一个项目“ x”,然后单击箭头按钮,那么您将看到完整的列表:

带下拉列表的AutoCompleteBox

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM