通用应用程序 – 加载combobox’ItemsSource async会产生奇怪的行为

在使用通用应用程序(目前仅在WP8.1方面)时,我偶然发现了以下奇怪的事情。

我有一个ComboBox,UserControl(位于WindowsPhone项目中)它被绑定到共享项目中的VM。 ItemsSource和SelectedItem都绑定到VM中各自的属性。

运行应用程序时,当您选择除第一个项目之外的任何项目时,它运行正常。 但是,当我选择第一个项目时,ComboBox中显示的字符串显示VM的.ToString() – 方法而不是……

(顺便说一句,这是一个简单的List ,所选项目是一个string 。它不能比那简单得多:p)

我创建了一个示例应用程序,只包含这个Combobox和VM。 我能够重现这一点,我异步填写绑定到ItemsSource的属性的那一刻。 从同步方法执行时,它可以工作。 但是从异步方法填充它只会产生上述问题。

一些截图:

第一个显示应用程序何时加载。 集合更改时,将选择列表的第一个元素。 它显示在这里:

在应用程序加载后

当您单击ComboBox时,您可以像往常一样查看其项目: 在此处输入图像描述

假设你点击第一个以外的任何元素,你仍然会得到正常的行为: 在此处输入图像描述

到目前为止,这很正常。 现在单击第一个项目。 你得到这个: 在此处输入图像描述

我尝试了各种各样的事情,比如把它作为一个对象的列表,而不仅仅是字符串。 将转换器添加到绑定对象,仅用于调试目的,仅显示实际的字符串值。 我不知道绑定的SelectedItem如何以及为什么突然显示ComboBox的DataContext …

你可以在这里下载示例应用程序: http : //1drv.ms/1DhklCQ (不包含二进制文件,只包含代码)

有人有任何想法吗?


编辑:重现此问题所需的代码:

创建一个空白的通用商店应用程序(8.1)。 在WindowsPhone项目中,文件MainPage.xaml:我添加了一个简单的combobox,并捕获Loaded事件。

  

在它的代码背后。 我已将DataContext分配给VM。 在Loaded事件中,我异步调用VM.LoadData()

 private VM _vm = new VM(); public MainPage() { this.InitializeComponent(); this.DataContext = _vm; } private async void Page_Loaded(object sender, RoutedEventArgs e) { await _vm.LoadDataAsync(); } 

VM对象定义如下:

 public class VM : INotifyPropertyChanged { private List _items; public List Items { get { return _items; } set { _items = value; _selectedItem = _items.FirstOrDefault(); RaisePropertyChanged("Items"); RaisePropertyChanged("SelectedItem"); } } private string _selectedItem; public string SelectedItem { get { return _selectedItem; } set { _selectedItem = value; RaisePropertyChanged("SelectedItem"); } } public VM() { } public async Task LoadDataAsync() { this.Items = new List() { "a", "b", "c", "d", "e", "f", }; } public event PropertyChangedEventHandler PropertyChanged; private void RaisePropertyChanged(string propName) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(propName)); } } } 

找到一个解决方法原因以前的解决方案没有解决我的问题。

只需在绑定和选择combobox的项目或索引之间添加一个暂停。

代码如下:

 myCombobox.ItemsSource = myList; await Task.Delay(100); myCombobox.SelectedIndex = 12; 

希望这可以帮助 !

我检查了一下,我看不出你的代码有任何问题,所以我猜这是ComboBox中的一个错误。

了解问题并找到真正的修复可能需要一些时间,因此我建议您使用一些适合您的解决方法。 我试过以下它似乎工作:

  1. 将VM中的Items属性更改为ObservableCollection类型
  2. 将VM的构造函数中的属性/字段初始化为空集合。
  3. 加载项目时,只需填充集合(使用Add()方法向其添加项目)而不是替换它。

编辑 :我如何填写测试它的示例。

 public class VM : INotifyPropertyChanged { private ObservableCollection _items; public ObservableCollection Items { get { return _items; } set { _items = value; _selectedItem = _items.FirstOrDefault(); RaisePropertyChanged("Items"); RaisePropertyChanged("SelectedItem"); } } private string _selectedItem; public string SelectedItem { get { return _selectedItem; } set { _selectedItem = value; RaisePropertyChanged("SelectedItem"); } } public VM() { this._items = new ObservableCollection(); } public async Task LoadDataAsync() { var items = new List() { "1", "b", "c", "d", "e", "f", "f", "f", "f", "f", "f", }; foreach (var i in items) { this._items.Add(i); } this.SelectedItem = items.FirstOrDefault(); } public event PropertyChangedEventHandler PropertyChanged; private void RaisePropertyChanged(string propName) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(propName)); } } } 

这对我来说很好。

不仅异步 – 如果在OnLoaded事件中放置_vm.Items = new List...而不是await _vm.LoadDataAsync(); – 你会得到同样的问题。

在设置DataContext之前设置项目时 ,似乎不会发生此问题。

另一件事是如果你没有从代码中设置Selected项,那么问题就不会出现(正如我已经尝试过的那样):

 public ObservableCollection Items { get { return _items; } set { _items = value; // _selectedItem = _items.FirstOrDefault(); RaisePropertyChanged("Items"); // RaisePropertyChanged("SelectedItem"); } } 

至于现在我不知道为什么会这样。