为什么我的下拉式感觉如此笨重?

Mat*_*don 6 c# wpf xaml

UserControl在WinForms/WPF Interop ElementHost控件中嵌入了一个XAML .控件非常简单 - 它只是一个带按钮的下拉列表 - 这是整个标记:

<UserControl x:Class="Rubberduck.UI.FindSymbol.FindSymbolControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:local="clr-namespace:Rubberduck.UI.FindSymbol"
             mc:Ignorable="d" 
             d:DesignHeight="27" d:DesignWidth="270">

    <UserControl.Resources>
        <local:DeclarationImageConverter x:Key="DeclarationImageConverter" />
    </UserControl.Resources>

    <UserControl.CommandBindings>
        <CommandBinding Command="local:FindSymbolControl.GoCommand" 
                        Executed="CommandBinding_OnExecuted"
                        CanExecute="CommandBinding_OnCanExecute"/>
    </UserControl.CommandBindings>

    <Grid>

        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="32" />
        </Grid.ColumnDefinitions>

        <ComboBox IsEditable="True"
                    ItemsSource="{Binding MatchResults}"
                    SelectedItem="{Binding SelectedItem, UpdateSourceTrigger=PropertyChanged}"
                    Text="{Binding SearchString, UpdateSourceTrigger=PropertyChanged}"
                    IsTextSearchCaseSensitive="False"
                    IsTextSearchEnabled="True"
                    TextSearch.TextPath="IdentifierName">
            <ComboBox.ItemTemplate>
                <DataTemplate DataType="local:SearchResult">
                    <StackPanel Orientation="Horizontal" VerticalAlignment="Center">
                        <Image Height="16" Width="16" Margin="2,0,2,0" Source="{Binding Declaration, Converter={StaticResource DeclarationImageConverter}}" />
                        <TextBlock Margin="2,0,2,0" Text="{Binding IdentifierName}" FontWeight="Bold" MinWidth="140" />
                        <TextBlock Margin="2,0,2,0" Text="{Binding Location}" />
                    </StackPanel>
                </DataTemplate>
            </ComboBox.ItemTemplate>
        </ComboBox>

        <Button Grid.Column="1"
                Command="local:FindSymbolControl.GoCommand">
            <Image Height="16" Source="pack://application:,,,/Rubberduck;component/Resources/arrow.png" />
        </Button>

    </Grid>
</UserControl>
Run Code Online (Sandbox Code Playgroud)

问题在于它不能可靠地工作,而且本能远非如此.

  • 如果我在框中键入实际匹配项目的内容,则在我在下拉列表中手动选择该项目之前不会发生任何事情.就像这里一样,我输入"sleepD",自动填充到"sleepDelay"的框,但命令仍然被禁用:

    键入

  • 一旦我在下拉列表中选择了该项目,命令按钮就会按预期启用(尽管按钮被禁用时按钮上的图像不会显示为灰色,因此它并不像我预期的那样明显是).

    (屏幕截图并未真正显示,但该搜索只有一个匹配)

  • 如果我在该点单击按钮,它将按预期工作.问题是,如果我之后从下拉列表中选择一个新选项,文本框将被清除而不是显示我选择的项目,并且有一个奇怪的延迟,在此期间框显示看似被选中的空格 - 这似乎只是在搜索文本与多个条目匹配时,在下拉列表中选择值之后进行上一次选择时发生,例如上面的"睡眠".

    wtf是这个选择的空白垃圾?

  • 清除框后,我可以从下拉列表中进行新选择,它将按预期工作(除了VBE实际上不会激活CodePane我将选择设置为,但这是一个单独的问题).


命令实现只会引发一个Navigate事件,该事件将a传递Declaration给拥有VM实例的代码.

Search方法,我需要在.Take(50)其后添加一个.Select,以限制返回结果的数量,并可能减少滞后一点:

    private void Search(string value)
    {
        var lower = value.ToLowerInvariant();
        var results = _declarations.Where(
            declaration => declaration.IdentifierName.ToLowerInvariant().Contains(lower))
            .OrderBy(declaration => declaration.IdentifierName.ToLowerInvariant())
            .Select(declaration => new SearchResult(declaration));

        MatchResults = new ObservableCollection<SearchResult>(results);
    }

    private string _searchString;

    public string SearchString
    {
        get { return _searchString; }
        set
        {
            _searchString = value; 
            Search(value);
        }
    }

    private SearchResult _selectedItem;

    public SearchResult SelectedItem
    {
        get { return _selectedItem; }
        set 
        { 
            _selectedItem = value; 
            OnPropertyChanged();
        }
    }

    private ObservableCollection<SearchResult> _matchResults;

    public ObservableCollection<SearchResult> MatchResults
    {
        get { return _matchResults; }
        set { _matchResults = value; OnPropertyChanged(); }
    }
}
Run Code Online (Sandbox Code Playgroud)

还有一个IValueConverter涉及的,它接受声明的枚举Declaration中的es SearchResultswitches DeclarationType返回指向.png图像的包uri以在下拉列表中使用.

Mat*_*don 0

啊啊找到了。它在 XAML 中。

就在这儿:

Text="{Binding SearchString, UpdateSourceTrigger=PropertyChanged}"
Run Code Online (Sandbox Code Playgroud)

那条线不属于那里;相反,绑定TextSearch.Text属性...

TextSearch.Text="{Binding SearchString, Mode=OneWayToSource, UpdateSourceTrigger=PropertyChanged}"
Run Code Online (Sandbox Code Playgroud)

使一切按预期进行。没有故障,没有滞后。嗯,当我第一次删除下拉列表时存在延迟,但这是另一个问题。

经验教训:当在TextSearch可编辑组合框上启用时,不要绑定该Text属性,除非您想要奇怪的行为。