我正在尝试加载一个列表框,其中包含从OData Web服务中提取的项目列表。数据获取工作正常,我正在获取项目列表。列表框实际上工作并显示项目,而不是每次我启动应用程序时...由于需要异步拉取数据,有时列表框会在数据返回之前加载。当它这样做时,我给它一个带有单个“空”项的列表,以指示数据仍在加载。几秒钟之后,数据已加载,我为列表引发了一个PropertyChanged事件。我在列表属性中的断点触发,当我检查列表包含正确的项目时。但列表框不显示新项目,只显示旧的“空”项。对我来说,xaml显然是在请求列表,但是不会刷新新项目的布局,这似乎有点奇怪。
首先是初始化ViewModel的代码。 ModelReferenceMap实现了INotifyPropertyChanged,因此应该在OnPropertyChanged(“Areas”)时更新视图;被调用(这会触发从属性中获取列表,但不会更新视图)。
public ModelReferenceMap(Uri serviceURI)
{
// Try initialising these lists to a non null but empty list
// in the hope it will stop the lists breaking when the service
// is a little bit slow...
areas = new List<ModelReferenceItem> { new ModelReferenceItem(null) };
// This is a ServiceReference entity context which will retrieve the data from the OData service
context = new LiveEntities(serviceURI);
// SendingRequest adds credentials for the web service
context.SendingRequest += context_SendingRequest;
// The query to retrieve the items
var areaQuery = from i in context.MigrationItems where i.FusionPTID == 0 && i.Type == "AreaType" orderby i.Name select i;
// On completion this asynccallback is called
AsyncCallback ac = iasyncResult =>
{
// Populates the List with the data items
areas = (from i in ((DataServiceQuery<MigrationItem>) areaQuery).EndExecute(iasyncResult)
select new ModelReferenceItem(i)).ToList();
foreach (ModelReferenceItem area in areas)
{
if (selectedArea == null)
selectedArea = area;
area.PropertyChanged += referenceItem_PropertyChanged;
}
// The Xaml Listbox has its ItemsSource bound to the Areas property. This should trigger a refresh of the listbox contents shouldn't it?
OnPropertyChanged("Areas");
OnPropertyChanged("SelectedArea");
};
// Start the query
((DataServiceQuery<MigrationItem>)areaQuery).BeginExecute(ac, null);
}
现在是XAML。请注意,列表框的DataContext是ReferenceMap(我的主ViewModel上的一个属性,它公开了ModelReferenceMap的单例实例)。然后我将ItemsSource绑定到Areas。
<ListBox Grid.Row="0" DataContext="{Binding ReferenceMap}" ItemsSource="{Binding Areas}" SelectedItem="{Binding SelectedArea, Mode=TwoWay}" HorizontalAlignment="Stretch" Margin="3" Name="listBoxFusionAreas" VerticalAlignment="Stretch">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Background="{Binding CompleteStatusColour}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock FontSize="12" Text="{Binding Name}" />
<TextBlock Grid.Column="1" FontSize="12" Text="{Binding Count}"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Areas属性正在触发,表明绑定正在运行。当仅在检索到服务数据之后请求区域(即仅一次)时,列表完美地工作。但是,如果在返回服务数据之前触发了Areas属性(即使用单个'empty'项),则会在OnPropertyChanged(“区域”)期间再次触发;使用完整的项目集调用,只有这次列表仍然只显示原始的“空”项目。
我做错了什么?
答案 0 :(得分:3)
每当您绑定到ViewModel中的集合时,您需要确定集合中的项目是否会发生变化?在您的情况下,您需要实现
ObservableCollection<ModelReferenceItem> areas ;
而不是
List<ModelReferenceItem> area;
ObservableCollection实现了INoifyCollectionChanged事件,该事件通知您的视图集合中的更改(添加/删除)