2011-07-23 38 views
0

讓我先展示代碼。Silverlight 4 +帶MVVM的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()); 
     } 
    } 

這次MessageBox會顯示3,這很好,因爲db中有3條記錄。所以它看起來像View和ViewModel之間存在問題。我懷疑我在這裏錯過了一件非常基本的事情。另外請注意,我知道這不是真正的MVVM,但我必須通過這種方式來完成這個程序。 我希望我的解釋清楚,謝謝你的幫助。

回答

0

在你的第一個辦法,這是不行的,代碼的流程:

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

不與您的WCF方法的異步調用的終止連接!換句話說,你展示了mbox,但是你不確定異步調用已經終止。

當然,您已將委派分配給GetVenuesCompleted事件,但toClient.GetVenuesAsync()的調用是異步調用,這意味着調用時不會等待結果(終止)。所以,當你撥打:

vvm.GetAllVenues(); 

然後

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

調用快那麼你的toClient_GetVenuesCompleted委託。

第二種方法的工作原理是當異步方法完成時(在GetVenues回調中)顯示消息框。

在我看來,你可以修復它,例如在VenueViewModel中添加一個新的事件GetAllVenuesCompleted,它將在toClient_GetVenuesCompleted委託的最後被觸發。換句話說,我會進一步傳遞這個事件。另外我會添加一個評論,GetAllVenues是一個異步方法。

+0

你說得對。你能告訴我是否有一個簡單的方法來決定vvm.GetAllVenues()調用是否完成?或者什麼是最好的方法? – rescueme

+0

通過在VenueViewModel中添加一個新事件GetAllVenuesCompleted,該事件將在toClient_GetVenuesCompleted委託的最後被觸發。換句話說,我會進一步傳遞這個事件。不知道更簡單更好的方法... – Pellared

0

我想問題是,你正在創建新的虛擬機。

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,填充數據即可。該虛擬機永遠不會再使用。 MainPage.xaml示例的規則相同。
你應該在構造函數/加載處理程序創建VenuViewModel的全局變量和調用其GetAllVenues在Loaded事件

相關問題