Работая над универсальным приложением (в настоящее время только на стороне WP8.1), я наткнулся на следующую странную вещь.
У меня есть ComboBox, UserControl (расположенный в проекте WindowsPhone), в котором он привязан к виртуальной машине в проекте Shared. И ItemsSource, и SelectedItem привязаны к своим соответствующим свойствам в виртуальной машине.
При запуске приложения при выборе любого пункта кроме первого работает отлично. Но когда я выбираю первый элемент, строка, отображаемая в ComboBox, вместо этого показывает .ToString()
-метод виртуальной машины...
(Кстати, это просто List<string>
, выбранный элемент — string
. Проще не бывает :p)
Я создал пример приложения, содержащего только этот Combobox и виртуальную машину. Мне удалось воспроизвести это, когда я асинхронно заполнил свойство, привязанное к ItemsSource. При выполнении синхронным методом это работает. Но просто заполнение его из асинхронного метода создает вышеуказанную проблему.
Несколько скриншотов:
Первый показывает приложение, когда оно загружено. При изменении коллекции выбирается первый элемент списка. Здесь показано:
Когда вы нажимаете на поле со списком, вы видите его элементы, как обычно:
Скажем, вы нажимаете на любой элемент, кроме первого, вы все равно получаете нормальное поведение:
Пока так нормально. Теперь щелкните первый элемент. Вы получите это:
...
Я пробовал разные вещи, такие как создание списка объектов, а не просто строк. Добавление преобразователя к привязанным объектам только в целях отладки показывает только фактические строковые значения. Я понятия не имею, как и почему привязанный SelectedItem внезапно показывает DataContext ComboBox...
Вы можете загрузить пример приложения здесь: http://1drv.ms/1DhklCQ (не содержит двоичных файлов, только код)
У кого-нибудь есть идеи?
РЕДАКТИРОВАТЬ: код, необходимый для воспроизведения этой проблемы:
Создайте пустое приложение универсального магазина (8.1). В проекте WindowsPhone файл MainPage.xaml: я добавил простое поле со списком и перехватил событие Loaded.
<ComboBox ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem}" />
В его коде позади. Я назначил DataContext виртуальной машине. И в событии 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));
}
}
}