我有一个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
,理论上,只要属性发生变化,它就应该更新UI:
private int _id;
public int ID
{
get { return _id; }
set
{
if (value != _id)
{
_id = value;
NotifyPropertyChanged("ID");
}
}
}
我有一个Web服务,它填充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
时,用户界面似乎不会自行更新。我做错了什么?
我看到的主要错误是这一行,特别是你评论的"这更新了模型":
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">
如果你打算拥有更多的功能,那就更好了。