У меня есть 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 в основном потоке также не повлияло на проблему.
Любая помощь будет оценена.