我在最近被重构为使用 MVVM 模式的 WPF 应用程序中有一个 ComboBox。此更改的一个明显副作用是,在组合框下拉列表可见时将焦点更改到另一个应用程序会完全阻止下拉列表再次可见,直到重新启动应用程序。
ComboBox DataContext 设置为我的 ViewModel,其 ItemsSource 绑定到一个ObservableCollection<String> SearchSuggestions
,并且 IsDropdownOpen 绑定到SuggestionsVisible
ViewModel 中的一个属性。
所需的效果是带有自动完成建议的搜索框。如果 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>();
}
OnKeyUp() 方法由 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 的分配对问题也没有影响。
任何援助将不胜感激。