Автообновление WP8 не работает на Binding
У меня есть приложение WP8 Pivot, в котором я связываю данные с XAML:
<phone:LongListSelector Grid.Row="1" Name="llsLocations" ItemsSource="{Binding}" SelectionChanged="LongListSelector_OnSelectionChanged">
<phone:LongListSelector.ItemTemplate>
<DataTemplate>
<Grid Margin="0,0,0,17">
<Image Source="{Binding Icon}" HorizontalAlignment="Left" Height="54" Width="69" />
<TextBlock Text="{Binding Location}" HorizontalAlignment="Left" Margin="80,0,0,0" />
....
....
В коде позади я назначаю DataContext следующим образом:
public MainPage()
{
InitializeComponent();
DataContext = App.ViewModel.Signs;
}
Объект ViewModel.Signs выглядит так:
public ObservableCollection<SignsViewModel> Signs { get; set; }
public MainViewModel()
{
Signs = new ObservableCollection<SignsViewModel>();
}
В пределах SignsViewModel
объект, у меня есть NotifyPropertyChanged
который в теории должен просто обновлять пользовательский интерфейс при изменении свойства:
private int _id;
public int ID
{
get { return _id; }
set
{
if (value != _id)
{
_id = value;
NotifyPropertyChanged("ID");
}
}
}
У меня есть веб-сервис, который заполняет Signs
объект:
private void GetSigns_Completed(object sender, OpenReadCompletedEventArgs e)
{
using (var sr = new StreamReader(e.Result))
{
var data = sr.ReadToEnd();
var results = JsonConvert.DeserializeObject<GetSignsResponse>(data);
App.ViewModel.Signs = results.Signs; // <--- This updates the Model
App.ViewModel.IsDataLoaded = true;
App.ViewModel.IsWaitingForData = false;
var storage = new DataStorage();
storage.SaveSigns(results.Signs);
}
}
Проблема в том, что когда я звоню в сервис и когда App.ViewModel.Signs
Пользовательский интерфейс не обновляется. Что я делаю неправильно?
1 ответ
Главное, что я вижу, это неправильно с этой строкой, особенно там, где вы прокомментировали "Это обновляет модель":
var results = JsonConvert.DeserializeObject<GetSignsResponse>(data);
App.ViewModel.Signs = results.Signs; // <--- This updates the Model
App.ViewModel.IsDataLoaded = true;
Наиболее вероятно, что вы нарушили ссылку на то, что ваш ViewModel.Signs
придерживается предыдущего ObservableCollection
,
В вашем MainViewModel
конструктор, вы уже установили Signs
собственность на new ObservableCollection<SignsViewModel>()
, Однако в строке выше вы заменили эту ссылку на results.Signs
,
Что бы я сделал, чтобы определить, если это проблема, вместо того, чтобы иметь
App.ViewModel.Signs = results.Signs; // <--- This updates the Model
Замени это
foreach (var sign in results.Signs) {
App.ViewModel.Signs.Add(sign);
}
Другие вещи, которые вы должны учитывать:
Ваш SignsViewModel
не нужно реализовывать INotifyPropertyChanged
(Я предполагаю, что у вас есть), если вы не хотите, чтобы обновленные изменения в ID
свойство распространяется, т.е. вы хотите, чтобы пользователь мог Edit
ID
значение. Если вы только отображаете их для просмотра, то нет необходимости реализовывать INotifyPropertyChanged
,
Я бы не рекомендовал устанавливать DataContext
всей страницы к чему-либо, кроме внешнего ViewModel. Скорее, чем
DataContext = App.ViewModel.Signs;
я бы выбрал
DataContext = App.ViewModel;
Тогда есть
<phone:LongListSelector Grid.Row="1" Name="llsLocations" ItemsSource="{Binding Signs}" SelectionChanged="LongListSelector_OnSelectionChanged">
Что немного лучше, если вы планируете иметь больше функциональности.