Что может помешать отображению раскрывающегося списка со списком после потери фокуса приложения?

У меня есть ComboBox в приложении WPF, которое недавно было реорганизовано для использования шаблона MVVM. Очевидным побочным эффектом этого изменения является то, что изменение фокуса на другое приложение, в то время как раскрывающийся список со списком отображается, полностью предотвращает повторное отображение раскрывающегося списка до тех пор, пока приложение не будет перезапущено.

ComboBox DataContext установлен на мою ViewModel, его ItemsSource привязан к ObservableCollection<String> SearchSuggestions, а IsDropdownOpen привязан к свойству SuggestionsVisible в ViewModel.

Желаемый эффект — окно поиска с предложениями автозаполнения. Он должен закрыться, если в ObservableCollection нет предложений, если пользователь отменяет поиск, если пользователь запускает поиск или если пользователь щелкает за пределами текстового поля — либо внутри приложения, либо вне его.

ViewModel явно устанавливает для свойства SuggestionsVisible значение true или false в зависимости от того, содержит ли SearchSuggesions какие-либо элементы после ввода пользователя. Этот процесс продолжает происходить после того, как эта ошибка проявляется, просто без видимых изменений в пользовательском интерфейсе. Любая идея, почему потеря фокуса при открытом раскрывающемся списке делает раскрывающийся список недоступным для остальной части сеанса приложения?

Вот как я соединяю вещи вместе:

<ComboBox DataContext="{Binding SearchBoxVm}" Name="cmboSearchField" Height="0.667" 
          VerticalAlignment="Top" IsEditable="True" StaysOpenOnEdit="True" 
          PreviewKeyUp="cmboSearchField_OnKeyUp" 
          PreviewMouseLeftButtonUp="cmboSearchField_OnPreviewMouseLeftButtonUp" 
          Background="White" ItemsSource="{Binding SearchTopics}" 
          IsDropDownOpen="{Binding SuggestionsVisible, 
          UpdateSourceTrigger=PropertyChanged}" 
          Margin="50.997,15.333,120.44,0" 
          RenderTransformOrigin="0.5,0.5" Grid.Row="1" >

<!-- SNIP STYLING -->
</ComboBox>

ViewModel:

public class SearchBoxViewModel : INotifyPropertyChanged
{
    public void ResetSearchField(bool preserveContents = false)
    {
        if (!preserveContents || string.IsNullOrEmpty(Query))
        {
            Foreground = Brushes.Gray;
            QueryFont = FontStyles.Italic;
            Query = DEFAULT_TEXT;
        }
    }

    public bool OnKeyUp(Key key)
    {
        bool showDropdown = SuggestionsVisible;
        bool changeFocusToCombobox = false;

        if (keyInValidRange(key))
        {
            SearchSuggestions = GetSearchSuggestions(Query);
            if (SearchSuggestions.Count > 0)
            {
                SuggestionsVisible = true;
            }
        }

        return changeFocusToCombobox;
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged(String propertyName = "")
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    bool _suggestionsVisible = false;
    public bool SuggestionsVisible 
    {
        get { return _suggestionsVisible; }
        set
        { 
                    // this section is still called after this issue manifests,
                    // but no visible change to the UI state is made
            _suggestionsVisible = value;
            NotifyPropertyChanged("SuggestionsVisible");
        }
    }

    public ObservableCollection<String> SearchTopics = new ObservableCollection<String>();
 }

Метод OnKeyUp() вызывается классом MainWindow (не удалось привязать события к обработчикам, указанным в ViewModel), а также есть вызов ResetSearechField из MainWindow:

// Note: removing references to this event handler does not have any effect
// on the issue at hand... only including here for completeness
void window_Deactivated(object sender, EventArgs e)
{
    SearchBoxVm.SuggestionsVisible = false; 
    SearchBoxVm.ResetSearchField(true);            
}

Я потратил довольно много времени, пытаясь отладить это, и не видел каких-либо внутренних изменений состояния, которые могли бы объяснить это. В остальном событие NotifyPropertyChanged ведет себя так же, как и раньше, и в окне трассировки стека не отображаются какие-либо возникшие исключения.

Установка режима привязки для свойства IsDropdownOpen на «TwoWay» в XAML также не имела никакого эффекта. Наконец, обертывание назначения SuggestionsVisible в вызове Dispatcher в основном потоке также не повлияло на проблему.

Любая помощь будет оценена.


person BrMcMullin    schedule 20.06.2013    source источник
comment
Не могли бы вы в нескольких словах описать, как работает ваша работа и какой она должна быть?   -  person Anatoliy Nikolaev    schedule 18.07.2013
comment
@Anatolyy Nikolaev - готово, смотрите третий абзац.   -  person BrMcMullin    schedule 18.07.2013
comment
@the wpf dev чувак - интересное предложение. Я установил высоту выпадающего списка на 25, но это не повлияло на внешний вид его drpodown. Я также пробовал играть со свойством MaxDropdownHeight, но это тоже не помогло.   -  person BrMcMullin    schedule 18.07.2013
comment
В вашем приложении может быть что-то еще, что вызывает это. Вы можете воспроизвести это в тестовом проекте? Я раньше использовал что-то подобное, и это работало без каких-либо проблем.   -  person Adrian Fâciu    schedule 19.07.2013
comment
Попробуйте изменить высоту или попробуйте изменить панель макета. Вместо этого используйте геттер и сеттер: public ObservableCollection‹String› SearchTopics = new ObservableCollection‹String›(); и вообще не используйте эти вещи KeyUp. Разместите фотографию своей проблемы, чтобы другие могли увидеть, как именно выглядит ваша проблема.   -  person ninja hedgehog    schedule 19.07.2013
comment
Возникают ли какие-либо исключения, когда вы пытаетесь открыть его? Сбрасывается ли ItemsSource или собирается мусор? Ломаются ли крепления при подвешивании?   -  person Nate Diamond    schedule 19.07.2013
comment
Опубликованный код выглядит нормально. Опубликуйте другие части кода, связанные с этим, возможно, код позади.   -  person ramaral    schedule 20.07.2013
comment
Разве SearchTopics не должно быть свойством, а не переменной? Можете ли вы удалить IsDropDownOpen, PreviewKeyUp и PreviewMouseLeftButtonUp, чтобы попытаться устранить проблему?   -  person is_this_the_way    schedule 22.07.2013
comment
Участник SearchTopics уже преобразован в свойство, но спасибо, что заметили это! @NateDiamond Вы знаете, я даже не знаю, как проверить, не нарушаются ли привязки, но не похоже, что ItemsSource подвергается сборке мусора.   -  person BrMcMullin    schedule 22.07.2013
comment
Если вы отлаживаете, проверьте свое окно вывода, чтобы увидеть, не говорит ли оно что-нибудь о каких-либо нарушенных привязках.   -  person Vynos    schedule 22.07.2013
comment
Похоже, что событие OnKeyUp — единственное место, где вы можете установить для SuggestionsVisible значение true. Вы пытались установить точку останова в коде, а затем запустить свою проблему, а затем посмотреть, нажимаете ли вы код на код, который возвращает его значение true?   -  person Nathan Dace    schedule 23.07.2013
comment
@PocketDews действительно у меня есть - вызывается код, который возвращает его значение true, и NotifyPropertyChanged все еще вызывается. Оттуда это черная дыра - он возвращается без каких-либо ошибок или исключений, но в пользовательском интерфейсе ничего не обновляется.   -  person BrMcMullin    schedule 23.07.2013
comment
Похоже, нет явных признаков того, что привязки нарушаются - ничего в окне вывода, даже после того, как я установил высокий уровень трассировки для рассматриваемых элементов...   -  person BrMcMullin    schedule 23.07.2013
comment
вы уверены, что когда вы возвращаетесь на свою страницу, SearchBoxViewModel является тем же экземпляром? поскольку очень распространенной ошибкой является изменение экземпляра, чтобы привязка застряла на старом экземпляре и не прослушивала новые уведомления.   -  person Pedro.The.Kid    schedule 23.07.2013


Ответы (1)


Вероятно, мне следует написать это как комментарий, но комментарии, к сожалению, не поддерживают изображения, поэтому я опубликую это как ответ, поэтому не стесняйтесь голосовать против, если это вообще не имеет значения.

@BrMcMullin, поскольку вы заявили, что:

Желаемый эффект — окно поиска с предложениями автозаполнения.

могу я спросить, почему вы решили использовать стандартный ComboBox вместо специализированного AutoCompleteBox, который доступен в WPF Toolkit — Выпуск за февраль 2010 г. и кажется, что он специально разработан для вашего случая?

Вы могли заметить, что первая ссылка указывает на документацию для его предшественника Silverlight, но не беспокойтесь — библиотека WPF Toolkit включает полнофункциональный официальный порт AutoCompleteBox для WPF из Silverlight. Дополнительная информация об этом «событии»: AutoCompleteBox: теперь на 100 % больше WPF< /а>.

С этим элементом управления ваше всплывающее окно автозаполнения может выглядеть так же просто, как:

Простой пример WPF AutoCompleteBox

или такой сложный, как:

Complex WPPF AutoCompleteBox

Итак, если вам не удастся решить проблему с видимостью всплывающего окна ComboBox, не стесняйтесь попробовать AutoCompleteBox. С его помощью вы даже можете использовать динамическую сортировку ваших предложений, если это необходимо (просто используйте ответ от @adabyron).

person Sevenate    schedule 23.07.2013
comment
Это фантастика - правильный инструмент для работы. Честно говоря, я даже не знал, что такой контроль существует. При поиске подходящего элемента управления WPF я продолжал искать такие вещи, как окно поиска. Мне никогда не приходило в голову искать поле автозаполнения - person BrMcMullin; 24.07.2013
comment
@BrMcMullin, да, это может сбивать с толку, вероятно, потому, что AutoCompleBox можно использовать во многих других случаях, чем просто окно поиска. Подумайте о любом текстовом поле в той или иной форме, которое пользователь будет заполнять более одного и относительно часто - автозаполнение неизмененных значений в некоторых из них будет очень удобно. - person Sevenate; 24.07.2013