Silverlight列表框不刷新列表

时间:2012-03-02 05:29:17

标签: xaml silverlight-4.0 listbox odata

我正在尝试加载一个列表框,其中包含从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(“区域”)期间再次触发;使用完整的项目集调用,只有这次列表仍然只显示原始的“空”项目。

我做错了什么?

1 个答案:

答案 0 :(得分:3)

每当您绑定到ViewModel中的集合时,您需要确定集合中的项目是否会发生变化?在您的情况下,您需要实现

ObservableCollection<ModelReferenceItem> areas ;

而不是

List<ModelReferenceItem> area;

ObservableCollection实现了INoifyCollectionChanged事件,该事件通知您的视图集合中的更改(添加/删除)