У меня есть XAML UserControl
, встроенный в WinForms/WPF Interop ElementHost
. Управления довольно просты - это просто выпадающие кнопки - вот вся разметка:Почему мое раскрывающееся меню выглядит таким неуклюжим?
<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>
Проблема заключается в том, что она не работает надежно и далеко от инстинктивно.
Если я ввожу что-то в поле, которое фактически соответствует элементу, ничего не происходит, пока я вручную не выберу этот элемент в раскрывающемся списке. Как здесь, я напечатал «sleepD», коробка автоматически появившейся в «SLEEPDELAY», но команда все еще отключен:
После того, как я выбрал этот пункт в раскрывающемся меню, кнопка команды получает включена как ожидалось (хотя изображение на кнопке не отображается серым цветом, когда кнопка отключена, поэтому это не так очевидно, как я предполагал).
(скриншот не на самом деле показывает, но есть только один матч для этого поиска)
Если я нажимаю кнопку в тот момент, он работает, как ожидалось. Проблема заключается в том, что если после этого вычеркнуть новый выбор из раскрывающегося списка, текстовое поле очистится, а не отобразит выбранный элемент, и будет странная задержка, в течение которой поле отображает то, что кажется выбранным пробелом - это кажется, только когда предыдущий выбор был сделан после выбора значения в раскрывающемся списке, в то время как текст поиска соответствует нескольким записям, например, «Сон» выше.
После того, как окно получил рассеялся, я могу сделать новый выбор из выпадающего списка, и он будет работать, как и ожидалось (кроме VBE не будет на самом деле активировать CodePane я устанавливающее выбор для, но это отдельный вопрос).
Реализация команды просто поднимает Navigate
событие, которое проходит 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(); }
}
}
Там также IValueConverter
участие, который принимает Declaration
в SearchResult
и switch
es в объявлении декларации DeclarationType
, чтобы вернуть пакет uri, который указывает на .png-изображение для использования в выпадающем списке.
Каков тип объектов в 'MatchResults'? –
Кроме того, пожалуйста, покажите реализацию команды –
. Все дело в [GitHub] (https://github.com/retailcoder/Rubberduck/tree/next/RetailCoder.VBE/UI/FindSymbol) - я отредактирую как скоро, как у меня есть шанс, я закрыл сейчас :(спасибо! –