我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"的框,但命令仍然被禁用:

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

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

清除框后,我可以从下拉列表中进行新选择,它将按预期工作(除了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 SearchResult和switches DeclarationType返回指向.png图像的包uri以在下拉列表中使用.
啊啊找到了。它是在 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属性,除非您想要奇怪的行为。