0

初めて、アプリにMVVMパターンを使用しました。ビュークラス、viewModelクラス、コマンドクラスを作成します。ボタンのビューをクリックすると、viewModelでバインディングコマンドを開始します。このコマンドでは、Webサービスからニュースをjson-objectとしてロードするためにHttpWebRequestを作成します。メソッド'GetNewsResponseCallback'で、データをjsonストリームとして取得します。シリアル化は正常に機能します。このメソッドで'PropertyChanged(this、new PropertyChangedEventArgs( "News"))'を呼び出すと、COMExceptionが発生します。ただし、ビューのリストビューを更新するには、PropertyChangeイベントが必要です。この問題を解決するにはどうすればよいですか?私のコマンドからサービスを開始するのは正しいですか?私はMVVM-Patternで開発するのは非常に新しいです。次の私のコードでは:

<Canvas>
    <Button Content="Aktualisieren"
            Canvas.Top="20"
            Canvas.Left="600"
            Command="{Binding SynchronizeNewsCommand}"/>

    <ListView x:Name="viewBox"
              ItemsSource="{Binding News}"
              ItemTemplate="{StaticResource newsTemplate}"/>

</Canvas>
public class MyCommand<T> : ICommand
    {
        readonly Action<T> callback;


        public MyCommand(Action<T> callback)
        {
            this.callback = callback;
        }


        public bool CanExecute(object parameter)
        {
            return true;
        }


        public event EventHandler CanExecuteChanged;


        public void Execute(object parameter)
        {
            if (callback != null) { callback((T)parameter); }
        }

    }



public class NewsViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        public ObservableCollection<NewsSerializer> News { get; set; }

        public MyCommand<object> SynchronizeNewsCommand { get; set; }


        public NewsViewModel()
        {
            SynchronizeNewsCommand = new MyCommand<object>(SynchronizeNews);
        }


        private void SynchronizeNews(object obj)
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Constans.uri);
            request.ContentType = "application/json; charset=utf-8";
            request.Accept = "application/json";
            request.Method = "POST";
            request.BeginGetRequestStream(new AsyncCallback(GetNewsRequestStreamCallback), request);
        }


        private void SynchronizeFinished(object obj)
        {
            PropertyChanged(this, new PropertyChangedEventArgs("News"));
        }


        private void GetNewsRequestStreamCallback(IAsyncResult asynchronousResult)
        {
            HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
            request.BeginGetResponse(new AsyncCallback(GetNewsResponseCallback), request);
        }


        private void GetNewsResponseCallback(IAsyncResult asynchronousResult)
        {
            HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;

            // End the operation
            HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asynchronousResult);
            Stream streamResponse = response.GetResponseStream();

            DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(ObservableCollection<NewsSerializer>));
            News = (ObservableCollection<NewsSerializer>)ser.ReadObject(streamResponse);

            PropertyChanged(this, new PropertyChangedEventArgs("News"));
        }

    }
4

1 に答える 1

1

通常、ObservableCollectionを使用する場合、毎回再作成するわけではありません。代わりにClear()を呼び出して(または削除されたアイテムを削除して)、新しいアイテムを1つずつ追加する必要があります。ビューには変更が自動的に通知され、PropertyChangedを呼び出す必要はありません。

    private void GetNewsResponseCallback(IAsyncResult asynchronousResult)
    {
        HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;

        // End the operation
        HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asynchronousResult);
        Stream streamResponse = response.GetResponseStream();

        DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(ObservableCollection<NewsSerializer>));
        var res = (IList<NewsSerializer>)ser.ReadObject(streamResponse);

        News.Clear();
        foreach(var item in res)
        {
            News.Add(item);
        }
    }

あなたの場合、AddRangeメソッドを実装してObservableCollectionクラスを拡張することも検討する必要があります。

于 2013-03-07T11:51:28.740 に答える