2012-03-02 81 views
1

我試圖加載一個列表框,列出了正在從OData Web服務中拉出的項目。數據抓取工作正常,我得到的項目列表。該列表框實際上工作並顯示項目,而不是每次啓動應用程序時...由於需要異步拉取數據,有時候列表框會在數據返回之前加載。當它給我一個單一的'空'項目列表,以表明數據仍在加載。幾秒鐘後,數據已經加載,我爲列表引發一個PropertyChanged事件。我在列表屬性觸發器中的斷點,當我檢查列表包含正確的項目。但是列表框不顯示新項目,只顯示舊的'空'項目。對我來說,看起來奇怪的是,xaml明確要求列表,但不刷新新項目的佈局。Silverlight列表框不刷新列表

首先初始化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綁定到區域。

 <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屬性在服務數據返回之前觸發(即使用單個'空'項目),它將在OnPropertyChanged(「Areas」)期間再次觸發;與全套項目打電話,只是這次列表仍然只顯示原來的'空'項目。

我在做什麼錯?

回答

3

無論何時綁定到ViewModel中的集合,都需要確保集合中的項是否會發生變化?你的情況,你需要實現

ObservableCollection<ModelReferenceItem> areas ; 

而不是

List<ModelReferenceItem> area; 

的ObservableCollection實現了通知你關於變更查看集合(添加/刪除)

+0

我給在INoifyCollectionChanged事件一個鏡頭,但是當服務最終返回數據時整個列表被替換。不是添加和刪除單個項目的情況。如果它不能立即工作,我會嘗試清除和添加,而不是替換現有的列表... – 2012-03-02 07:10:56

+0

似乎已經完成了這個伎倆。地區現在是ObservableCollection 。當數據返回時,我調用areas.Clear();然後areas.Add();在處理單個項目時,即添加事件處理程序。爲快速響應歡呼。 – 2012-03-02 07:38:06

+0

p.s.該死的確定我在幾年前遇到了這個......但我想這就是當你在iOS上開發18個月時會發生什麼情況:( – 2012-03-02 07:38:52