2015-05-21 4 views
6

У меня есть 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», но команда все еще отключен:

    typed "sleepD", autocompleted to "sleepDelay", but command is still disabled

  • После того, как я выбрал этот пункт в раскрывающемся меню, кнопка команды получает включена как ожидалось (хотя изображение на кнопке не отображается серым цветом, когда кнопка отключена, поэтому это не так очевидно, как я предполагал).

    "sleepDelay" works once it's selected from the dropdown

    (скриншот не на самом деле показывает, но есть только один матч для этого поиска)

  • Если я нажимаю кнопку в тот момент, он работает, как ожидалось. Проблема заключается в том, что если после этого вычеркнуть новый выбор из раскрывающегося списка, текстовое поле очистится, а не отобразит выбранный элемент, и будет странная задержка, в течение которой поле отображает то, что кажется выбранным пробелом - это кажется, только когда предыдущий выбор был сделан после выбора значения в раскрывающемся списке, в то время как текст поиска соответствует нескольким записям, например, «Сон» выше.

    wtf is this selected whitespace crap?

  • После того, как окно получил рассеялся, я могу сделать новый выбор из выпадающего списка, и он будет работать, как и ожидалось (кроме 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-изображение для использования в выпадающем списке.

+0

Каков тип объектов в 'MatchResults'? –

+0

Кроме того, пожалуйста, покажите реализацию команды –

+0

. Все дело в [GitHub] (https://github.com/retailcoder/Rubberduck/tree/next/RetailCoder.VBE/UI/FindSymbol) - я отредактирую как скоро, как у меня есть шанс, я закрыл сейчас :(спасибо! –

ответ

0

Aaah нашел его. Это было все в XAML.

Прямо здесь:

Text="{Binding SearchString, UpdateSourceTrigger=PropertyChanged}" 

Эта линия не принадлежит там; связывание TextSearch.Text свойства вместо ...

TextSearch.Text="{Binding SearchString, Mode=OneWayToSource, UpdateSourceTrigger=PropertyChanged}" 

делает всю работу по назначению. Никаких сбоев, нет отставания. Хорошо там отставание, когда я сначала бросаю выпадающий список, но это еще одна проблема.

Извлеченный урок: когда TextSearch включен в редактируемой combobox, не привязывайте свойство Text, если вы не хотите странного поведения.

Смежные вопросы