OData Webサービスから取得されたアイテムのリストをリストボックスにロードしようとしています。データの取り込みがうまくいき、アイテムのリストを取得しています。リストボックスは実際に動作し、アイテムを表示しますが、アプリケーションを起動するたびに表示されるわけではありません。非同期にデータを取得する必要があるため、データが返される前にリストボックスがロードされることがあります。それが実行されると、データがまだ読み込まれていることを示すために、1つの「空の」項目を含むリストをフィードします。秒後にデータがロードされ、リストの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(ModelReferenceMapのシングルトンインスタンスを公開するメインのViewModelのプロパティ)です。私は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>
領域プロパティは、バインディングが機能していることを正しくトリガーしています。サービスデータが検索された後(つまり1回だけ)、エリアが要求されると、リストは完全に機能します。ただし、サービスデータが返される前にAreasプロパティがトリガされた場合(つまり、単一の '空'アイテムの場合)、OnPropertyChanged( "Areas")中に再びトリガされます。今度は、リストには元の「空の」項目だけが表示されます。
私は間違っていますか?
を実装する必要がありますしかし、サービスが最終的にデータを返すときにリスト全体が置き換えられます。個々のアイテムを追加したり削除したりすることはあまりありません。それがすぐに動作しない場合は、既存のリストを置き換えるのではなく、明確で追加して試してみます... –
このトリックを完了したと思われます。エリアはObservableCollectionになりました。データが返ってきたら、私はareas.Clear()を呼び出します。次に、areas.Add();処理されている個々のアイテム、つまりイベントハンドラを追加します。クイックレスポンスへの歓声。 –
p.s.確かに私は数年前にこの問題に遭遇しました...しかし、私はあなたが18ヶ月間iOS上で開発していくとどうなるのでしょうか?( –