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

时间:2013-06-20 22:53:25

标签: c# wpf combobox

我在WPF应用程序中有一个ComboBox,最近已经重构为使用MVVM模式。对此更改的明显副作用是,在组合框下拉列表可见时将焦点更改为另一个应用程序可以完全防止下拉列表再次显示,直到应用程序重新启动。

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

所需效果是带有自动填充建议的搜索框。如果ObservableCollection中没有建议,如果用户取消搜索,用户运行搜索,或者用户点击文本字段 - 应用程序内部或外部,都应该关闭。

ViewModel根据SearchSuggesions是否包含用户输入后的任何项目,将SuggestionsVisible属性显式设置为true或false。在此错误显现之后,此过程将继续发生,只是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>();
 }

OnWeyUp()方法由MainWindow类调用(尚未达到绑定事件到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事件的行为与以前一样,并且堆栈跟踪窗口没有显示遇到的任何异常。

在XAML中将IsDropdownOpen属性的绑定模式设置为“TwoWay”也没有任何效果。最后,在主线程的Dispatcher调用中将赋值包装到SuggestionsVisible也不会对该问题产生影响。

任何帮助都将不胜感激。

1 个答案:

答案 0 :(得分:1)

我可能应该把它写成评论,但不幸的是,评论不支持图片,因此我会将其作为答案发布,如果这根本不相关,请随意投票。

@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的答案)。