2011-07-23 5 views
0

コードを最初に表示させてください。MVVMを使用したSilverlight 4 + WCF:何らかの理由でコレクションにデータが格納されない

WCFのServiceContract機能:

public List<VenueData> GetVenues() 
    { 
     List<VenueData> listOfVenues = new List<VenueData>(); 

     string connString = @"...."; 

     DataContext dc = new DataContext(connString); 
     Table<VenueData> venues = dc.GetTable<VenueData>(); 

     listOfVenues = (from v in venues 
         select v).ToList(); 

     return listOfVenues; 
    } 

VenueViewModel.cs

public class VenueViewModel : ViewModelBase 
{ 
    private VenueData _venue; 
    private ObservableCollection<VenueData> _venues = new ObservableCollection<VenueData>();   

    public VenueData Venue 
    { 
     get 
     { 
      return _venue; 
     } 
     set 
     { 
      if (_venue != value) 
      { 
       _venue = value; 
       OnNotifyPropertyChanged("Venue"); 
      } 
     } 
    } 

    public ObservableCollection<VenueData> Venues 
    { 
     get 
     { 
      return _venues; 
     } 
     set 
     { 
      if (_venues != value) 
      { 
       _venues = value; 
       OnNotifyPropertyChanged("Venues"); 
      } 
     } 
    } 

    public void GetAllVenues() 
    { 

     TicketOrderWcfClient toClient = new TicketOrderWcfClient(); 
     toClient.GetVenuesCompleted += new EventHandler<GetVenuesCompletedEventArgs>(toClient_GetVenuesCompleted); 
     toClient.GetVenuesAsync();    
    } 

    void toClient_GetVenuesCompleted(object sender, GetVenuesCompletedEventArgs e) 
    { 
     if (e.Error == null) 
      Venues = e.Result; 
    } 
} 

MainPage.xamlを(ビュー)

public MainPage() 
    { 
     InitializeComponent(); 
     Loaded += new RoutedEventHandler(MainPage_Loaded); 
    } 

    void MainPage_Loaded(object sender, RoutedEventArgs e) 
    { 
     VenueViewModel vvm = new VenueViewModel(); 
     vvm.GetAllVenues(); 

     MessageBox.Show(vvm.Venues.Count.ToString()); 

    } 

まあ、これはコードのほとんどです。問題は、MainPage_Loadedイベントでvvm.GetAllVenues()がVenues ObservableCollectionに値を設定しないことです。 MessageBoxは0を表示します。私はwcfサービスが良好であることをテストしました。また、フィドラーは石鹸をうまく示しました。また、MainPage_Loadedイベントでwcfサービスを呼び出すと、動作します。以下を参照してください:

void MainPage_Loaded(object sender, RoutedEventArgs e) 
    { 

     TicketOrderWcfClient toClient = new TicketOrderWcfClient(); 
     toClient.GetVenuesCompleted += new EventHandler<GetVenuesCompletedEventArgs>(toClient_GetVenuesCompleted); 
     toClient.GetVenuesAsync(); 
    } 


    void toClient_GetVenuesCompleted(object sender, GetVenuesCompletedEventArgs e) 
    { 
     if(e.Error == null) 
     { 
      VenueViewModel vvm = new VenueViewModel(); 
      vvm.Venues = e.Result; 
      MessageBox.Show(vvm.Venues.Count.ToString()); 
     } 
    } 

この時間メッセージボックスがデシベルで3つのレコードがあるので、良いである、3が表示されます。したがって、ViewとViewModelの間に問題があるように見えます。私はここでかなり基本的なものがないと思う。また、私はこれが真のMVVMではないことを知っていることに注意してください、しかし、私はこの方法でこのプログラムを達成しなければなりません。 私の説明がはっきりしていることを願っています。ご協力いただきありがとうございます。

答えて

0

にそのGetAllVenuesを呼び出す必要があります:

MessageBox.Show(vvm.Venues.Count.ToString()); 

ではありませんWCFメソッドの非同期呼び出しの終了と関連しています。言い換えれば、mboxを表示しますが、非同期呼び出しが終了したことを確認することはありません。

もちろん、GetVenuesCompletedイベントに代理人を割り当てましたが、toClient.GetVenuesAsync()の呼び出しは非同期呼び出しであり、呼び出されると結果(終了)を待たないことを意味します。だから、あなたが呼び出すとき:

vvm.GetAllVenues(); 

を次に

MessageBox.Show(vvm.Venues.Count.ToString()); 

をすばやくtoClient_GetVenuesCompletedデリゲートその後、呼び出されます。

2番目の方法は、(GetVenuesコールバックで)非同期メソッドが完了したときにメッセージボックスを表示するためです。

私の意見では、toClient_GetVenuesCompletedデリゲートの最後で発生するVenueViewModelに新しいイベントGetAllVenuesCompletedを追加するなどして修復できます。言い換えれば、私はこのイベントをさらに進めるだろう。さらに、GetAllVenuesは非同期メソッドであるというコメントを追加します。

+0

あなたは正しいです。vvm.GetAllVenues()コールが終了したかどうかを判断する簡単な方法があるかどうか教えてください。または、最良のアプローチは何ですか? – rescueme

+0

toClient_GetVenuesCompletedデリゲートの最後で発生するVenueViewModelに新しいイベントGetAllVenuesCompletedを追加します。言い換えれば、私はこのイベントをさらに進めるだろう。より簡単で良い方法については考えていません... – Pellared

0

私は問題は、あなたが新しいVMを作成していると思います。

void toClient_GetVenuesCompleted(object sender, GetVenuesCompletedEventArgs e) 
{ 
    if(e.Error == null) 
    { 
     VenueViewModel vvm = new VenueViewModel(); 
     vvm.Venues = e.Result; 
     MessageBox.Show(vvm.Venues.Count.ToString()); 
    } 
} 

私は、このコードはうまくいくと思います。新しいVenueViewModelを作成し、データで埋めてください。それだけです。このVMは決して再び使用されません。 MainPage.xamlサンプルと同じ規則です。
あなたは、コンストラクタ/ロードハンドラでVenuViewModelのグローバル変数を作成し、コードの流れを動作しませんあなたの最初のアプローチでは、Loadedイベント

関連する問題