2011-07-23 40 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事件

相关问题