Автообновление 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">

Что немного лучше, если вы планируете иметь больше функциональности.

Другие вопросы по тегам