什么可能会阻止我的组合框下拉显示应用程序重点丢失后?

问题描述:

我在最近被重构为使用MVVM模式的WPF应用程序中有一个ComboBox。这种变化的一个明显的副作用是,当组合框下拉菜单可见时,将焦点转移到另一个应用程序可以完全防止再次显示下拉菜单,直到应用程序重新启动。什么可能会阻止我的组合框下拉显示应用程序重点丢失后?

ComboBox DataContext设置为我的ViewModel,其ItemsSource绑定到ObservableCollection<String> SearchSuggestions,IsDropdownOpen绑定到ViewModel中的属性SuggestionsVisible

想要的效果是一个带有自动填充建议的搜索框。如果ObservableCollection中没有任何建议,用户取消搜索,用户运行搜索,或者用户从文本字段中单击 - 无论是在应用程序内部还是在外部,都应该关闭它。

根据SearchSuggesions是否包含用户输入后的任何项目,ViewModel显式将SuggestionsVisible属性设置为true或false。这个过程继续发生在这个bug出现之后,只是没有明显的UI改变。任何想法为什么在下拉列表打开时失去焦点会导致下拉菜单对应用程序的其余部分无法打开?

以下是我有东西连接在一起:

<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> 

视图模型:

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()方法是由主窗口类名为(还没有得到尽可能结合事件在ViewModel中指定的处理程序),但是还有一个调用MainWindow的ResetSearechField:

// 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属性上的绑定模式设置为XAML中的'TwoWay'也没有任何效果。最后,在主线程的Dispatcher调用中将赋值包装到SuggestionsVisible中也不会对问题产生任何影响。

任何援助将不胜感激。

+1

你能用几句话来描述你的工作和应该怎么做? –

+0

@Anatoliy Nikolaev - 完成了,请看第三段。 – BrMcMullin

+0

@ wpf dev dude - 有趣的建议。我将组合框的高度设置为25,但不影响其drpodown的外观。我也尝试玩MaxDropdownHeight属性,但这也没有帮助。 – BrMcMullin

我可能应该把它写成评论,但不幸的是,评论不支持图片,所以我会张贴这个作为答案,所以如果这根本没有关系,可以随意投票。

@BrMcMullin,既然你说:

的预期效果是自动完成建议的搜索框。

请问,你为什么选择使用标准的ComboBox,而不是专门AutoCompleteBox可用在WPF Toolkit - February 2010 Release,似乎像你的情况是特别设计?

您可能已经注意到第一个链接指向其Silverlight前任的文档,但不用担心 - WPF Toolkit库包含Silverlight的AutoCompleteBox的全功能官方WPF端口。有关于此“事件”的更多信息:AutoCompleteBox: Now with 100% more WPF

与对照你自动完成弹出可能看起来那样简单:

Simple WPF AutoCompleteBox sample

或复杂如:

Complex WPPF AutoCompleteBox

所以,如果你不设法解决您的问题与ComboBox的弹出可见性,随意尝试AutoCompleteBox。有了它,你甚至可以利用dynamic sorting of your suggestions如果需要(只需使用@adabyron的答案)。

+0

这太棒了 - 这项工作的正确工具。老实说,我甚至不知道这个控制是存在的。当寻找合适的WPF控件时,我一直在搜索“搜索框”等内容。我从来没有想过要找到“自动完成框” – BrMcMullin

+0

@BrMcMullin,也许是因为AutoCompleBox可以用在许多情况下,然后只是搜索框。想想用某种形式表示的任何文本框,用户将会填充更多的文本框并且相对频繁 - 在其中一些文本框中自动完成未更改的值将非常方便。 – Sevenate