WP7 – コレクションに追加ディスパッチャ間

私は、 HttpWebRequest
Deployment.Current.Dispatcher.BeginInvoke()を使用してバックグラウンドでTwitterフィードからXMLをダウンロードし、結果を処理して私の
ListBoxItemsSource
私が今やりたいことは、複数のtwitterフィードからXMLを集め、コレクションにまとめ、
ItemsSource プロパティに割り当てます。

私は、クラス内のカウンタとクラス内のコレクションを使用し、要求が完了するたびにカウンタを更新し、カウンタがフィードカウント(7)に達すると、
ItemsSource それに応じて。問題は、私はC#/
WP7の新機能で、ここにいくつかの問題があることです。これは私が今作業しているものですが、明らかに間違っています。要求が最後に終了してを上書きしてしまい、「グローバル」コンテナに貼り付ける方法がわからないためですディスパッチャのように異なるスコープがあります:

string[] feeds = { "badreligion",
                "DoctorGraffin",
                "BrettGurewitz",
                "jay_bentley",
                "brtour",
                "GregHetson",
                "theBRpage" };

// invoked in the constructor
private void StartTwitterUpdate()
{
    foreach (string feed in feeds)
    {
        HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(new Uri("http://api.twitter.com/1/statuses/user_timeline.xml?screen_name=" + feed));

        request.BeginGetResponse(new AsyncCallback(twitter_DownloadStringCompleted), request);
    }
}

// the AsyncCallback
void twitter_DownloadStringCompleted(IAsyncResult asynchronousResult)
{
    HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;

    HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asynchronousResult);

    using (StreamReader streamReader1 =
        new StreamReader(response.GetResponseStream()))
    {
        string resultString = streamReader1.ReadToEnd();

        XElement xmlTweets = XElement.Parse(resultString);

       //here I need to add to a collection, and if the max is hit, set the ItemsSource
        Deployment.Current.Dispatcher.BeginInvoke(() =>
        {
            TwitterListBox.ItemsSource = from tweet in xmlTweets.Descendants("status")
                                            select new TwitterItem
                                            {
                                                CreatedAt = tweet.Element("created_at").Value,
                                                Id = tweet.Element("id").Value,
                                                ImageSource = tweet.Element("user").Element("profile_image_url").Value,
                                                Message = tweet.Element("text").Value,
                                                UserName = "@" + tweet.Element("user").Element("screen_name").Value
                                            };
        });
    }
}

EDIT Also, if it matters, I’ll have to sort the
final collection before sending it to ItemsSource, via
TwitterItem.CreatedAt, so if someone could suggest an
optimal data structure for sorting and easy
ItemsSource assignment, that’d be great!

ベストアンサー

必要なのは、永続的なバインド可能なコレクションオブジェクトをビューのどこかに作成し、そのオブジェクトをItemsSourceに一度割り当てることです。新しいアイテムが届くと、それらをコレクションに追加するだけです。

コレクションが変更されたときに通知をサポートする既存のコレクションタイプを選択するか、自分でコレクションタイプを実装するかのどちらかです。
Silverlightでは、あなたのベスト(唯一の)ベットは
System.Collections.ObjectModel.ObservableCollection
だと思います。もう1つのオプションは、異なるタイプのCollectionから継承するカスタムクラスに
System.Collections.Specialized.INotifyCollectionChanged
を実装することです。

並べ替えに関しては、到着するデータが常に既存のデータよりも遅れている場合、新しいアイテムをコレクションに追加する前に並べ替えることができます(コレクションの前に挿入することもできます彼らはトップに最新のものを持っています)。

ただし、新しいレコードが追加されるたびにコレクション全体をソートする必要がある場合は、アイテムクラスに
System.IComparable を実装する必要があります。この場合、次の方法をお勧めします。

System.Collection.Generic.List
(これにはネイティブのSort()メソッドが含まれています)に基づいて新しいコレクションクラスを作成します。

このクラスに INotifyCollectionChanged
を実装し、レコードが追加およびソートされた後に
NotifyCollectionChangedAction.Reset アクションで
CollectionChanged イベントを発生させます。

アイテムクラスに IComparable
を実装して、ルールに従ってソートされたアイテムを取得します。

INotifyCollectionChangedの実装による更新

ほとんどの提案はかなり単純ですが、INotifyCollectionChangedの実装はややこしいので、ここに含めてみましょう:

 _
Private m_ListChangedEvent As NotifyCollectionChangedEventHandler

''' 
''' This event is raised whenever the list is
changed and implements the IBindingList ListChanged event
'''
 
''' 
''' 
''' 
Public Custom Event ListChanged As NotifyCollectionChangedEventHandler Implements INotifyCollectionChanged.CollectionChanged
     _
    AddHandler(ByVal value As NotifyCollectionChangedEventHandler)
        m_ListChangedEvent = DirectCast([Delegate].Combine(m_ListChangedEvent, value), NotifyCollectionChangedEventHandler)
    End AddHandler

     _
    RemoveHandler(ByVal value As NotifyCollectionChangedEventHandler)
        m_ListChangedEvent = DirectCast([Delegate].Remove(m_ListChangedEvent, value), NotifyCollectionChangedEventHandler)
    End RemoveHandler

    RaiseEvent(ByVal sender As Object, ByVal e As NotifyCollectionChangedEventArgs)
        If m_ListChangedEvent IsNot Nothing Then
            m_ListChangedEvent.Invoke(sender, e)
        End If
    End RaiseEvent
End Event

消費者がリストの変更を認識できるようにこのイベントを発生させるには:

Call RaiseListChangedEvent(New NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset))

コメントする

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です