在使用通用应用程序(目前只在WP8.1版本上)时,我偶然发现了以下奇怪的事情。
我有一个ComboBox,它所在的UserControl(位于WindowsPhone项目中)绑定到共享项目中的VM。 ItemsSource和SelectedItem都绑定到VM中各自的属性。
运行应用程序时,当您选择除第一个项目之外的任何项目时,它运行正常。但是,当我选择第一个项目时,ComboBox中显示的字符串显示VM的.ToString()
- 方法而不是......
(顺便说一下,它只是一个简单的List<string>
,所选项目是string
。它不会比这简单得多:p)
我已经创建了一个示例应用程序,其中只包含此Combobox和VM。我能够重现这一点,我异步填写绑定到ItemsSource的属性的那一刻。从同步方法执行时,它可以工作。但是从异步方法填充它会产生上述问题。
一些屏幕截图:
第一个显示应用程序何时加载。集合更改时,将选择列表的第一个元素。它显示在这里:
当您单击ComboBox时,您可以像往常一样查看其项目:
假设你点击第一个以外的任何元素,你仍然会得到正常的行为:
到目前为止,这很正常。现在单击第一个项目。你得到这个:
...
我尝试了各种各样的事情,比如把它作为一个对象列表而不仅仅是字符串。将转换器添加到绑定对象,仅用于调试目的,仅显示实际的字符串值。我不知道绑定的SelectedItem如何以及为什么突然显示ComboBox的DataContext ...
您可以在此处下载示例应用: http://1drv.ms/1DhklCQ (不包含二进制文件,只包含代码)
有人有任何想法吗?
编辑:重现此问题所需的代码:
创建一个空白的通用商店应用(8.1)。 在WindowsPhone项目中,MainPage.xaml文件: 我添加了一个简单的组合框,并捕获Loaded事件。
<ComboBox ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem}" />
在它的代码背后。我已将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<string> _items;
public List<string> 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<string>()
{
"a",
"b",
"c",
"d",
"e",
"f",
};
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string propName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
}
答案 0 :(得分:7)
找到一种解决方法导致以前的解决方案无法解决我的问题。
只需在绑定和选择组合框的项目或索引之间添加暂停。
以下代码:
myCombobox.ItemsSource = myList;
await Task.Delay(100);
myCombobox.SelectedIndex = 12;
希望这有帮助!
答案 1 :(得分:2)
我检查了一下,我发现你的代码没有任何问题,所以我猜这是ComboBox中的一个错误。
了解问题并找到真正的修复可能需要一些时间,因此我建议您使用一些适合您的解决方法。我尝试了以下内容,似乎有效:
ObservableCollection<string>
Add()
方法向其添加项目),而不是替换它。编辑:我如何填写测试的示例。
public class VM : INotifyPropertyChanged
{
private ObservableCollection<string> _items;
public ObservableCollection<string> 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<string>();
}
public async Task LoadDataAsync()
{
var items = new List<string>() {
"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));
}
}
}
这对我来说很好。
答案 2 :(得分:1)
不仅是异步的 - 如果您将_vm.Items = new List...
放入 OnLoaded 事件而不是await _vm.LoadDataAsync();
- 您将遇到同样的问题。
似乎在设置DataContext之前设置 Items 后,问题就不会发生。
另一件事是,如果你没有从代码中设置所选项目,问题就不会出现(正如我已经尝试过的那样):
public ObservableCollection<string> Items
{
get { return _items; }
set
{
_items = value;
// _selectedItem = _items.FirstOrDefault();
RaisePropertyChanged("Items");
// RaisePropertyChanged("SelectedItem");
}
}
至于现在,我不知道为什么会这样。