2012-05-13 52 views
0

我正在玩弄創建Windows Phone應用程序。我一直在看this tutorial,但我有一些問題,視圖不更新與數據(模板只是空的)。Windows Phone中的UI Silverlight不更新

我已經確定了項目集合與實際數據集,但我懷疑這是一個不正確的發射活動NotifyPropertyChanged。

我可能會丟失什麼?

我MainViewModel看起來是這樣的:

public class MainViewModel : INotifyPropertyChanged 
{ 
    private ServiceAgent _serviceAgent; 
    public MainViewModel() 
    { 
     this.Items = new ObservableCollection<SocialListItemViewModel>(); 
     if (_serviceAgent == null) 
     { 
      _serviceAgent = new ServiceAgent(); 
     } 
    } 

    /// <summary> 
    /// A collection for ItemViewModel objects. 
    /// </summary> 
    public ObservableCollection<SocialListItemViewModel> Items { get; private set; } 

    public bool IsDataLoaded 
    { 
     get; 
     private set; 
    } 

    /// <summary> 
    /// Creates and adds a few ItemViewModel objects into the Items collection. 
    /// </summary> 
    public void LoadData() 
    { 
     _serviceAgent.GetSocialItems(); 
     _serviceAgent.SocialItemsLoaded += new ServiceAgent.SocialListItemsLoadedEventHandler(_serviceAgent_SocialItemsLoaded); 

     //// Sample data; replace with real data 
     //this.Items.Add(new SocialListItemViewModel() { ContentShort = "Facilisi faucibus habitant inceptos interdum lobortis nascetur pharetra placerat pulvinar sagittis senectus sociosqu", ImageUrl = "http://profile.ak.fbcdn.net/hprofile-ak-ash2/50215_277666338969761_534345200_t.jpg" }); 
     //this.Items.Add(new SocialListItemViewModel() { ContentShort = "Habitant inceptos interdum lobortis nascetur pharetra placerat pulvinar sagittis senectus sociosqu suscipit torquent", ImageUrl = "http://profile.ak.fbcdn.net/hprofile-ak-ash2/50215_277666338969761_534345200_t.jpg" }); 
     //this.Items.Add(new SocialListItemViewModel() { ContentShort = "Ultrices vehicula volutpat maecenas praesent accumsan bibendum dictumst eleifend facilisi faucibus habitant inceptos", ImageUrl = "http://profile.ak.fbcdn.net/hprofile-ak-ash2/50215_277666338969761_534345200_t.jpg" }); 
     //this.Items.Add(new SocialListItemViewModel() { ContentShort = "Maecenas praesent accumsan bibendum dictumst eleifend facilisi faucibus habitant inceptos interdum lobortis nascetur", ImageUrl = "http://profile.ak.fbcdn.net/hprofile-ak-ash2/50215_277666338969761_534345200_t.jpg" }); 

     this.IsDataLoaded = true; 
    } 

    void _serviceAgent_SocialItemsLoaded(ObservableCollection<SocialListItemViewModel> socialItems) 
    { 
     Deployment.Current.Dispatcher.BeginInvoke(() => 
                 { 

                  this.Items = socialItems; 

                  //this.Items.Add(new SocialListItemViewModel() { ContentShort = "Facilisi faucibus habitant inceptos interdum lobortis nascetur pharetra placerat pulvinar sagittis senectus sociosqu", ImageUrl = "http://profile.ak.fbcdn.net/hprofile-ak-ash2/50215_277666338969761_534345200_t.jpg" }); 
                  //this.Items.Add(new SocialListItemViewModel() { ContentShort = "Habitant inceptos interdum lobortis nascetur pharetra placerat pulvinar sagittis senectus sociosqu suscipit torquent", ImageUrl = "http://profile.ak.fbcdn.net/hprofile-ak-ash2/50215_277666338969761_534345200_t.jpg" }); 
                  //this.Items.Add(new SocialListItemViewModel() { ContentShort = "Ultrices vehicula volutpat maecenas praesent accumsan bibendum dictumst eleifend facilisi faucibus habitant inceptos", ImageUrl = "http://profile.ak.fbcdn.net/hprofile-ak-ash2/50215_277666338969761_534345200_t.jpg" }); 
                  //this.Items.Add(new SocialListItemViewModel() { ContentShort = "Maecenas praesent accumsan bibendum dictumst eleifend facilisi faucibus habitant inceptos interdum lobortis nascetur", ImageUrl = "http://profile.ak.fbcdn.net/hprofile-ak-ash2/50215_277666338969761_534345200_t.jpg" }); 
                  NotifyPropertyChanged("ContentShort"); 
                 }); 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 
    private void NotifyPropertyChanged(String propertyName) 
    { 
     PropertyChangedEventHandler handler = PropertyChanged; 
     if (null != handler) 
     { 
      handler(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 
} 

視圖模型看起來是這樣的:

[DataContract] 
public class SocialListItemViewModel : INotifyPropertyChanged 
{ 

    private string _contentshort; 
    /// <summary> 
    /// Sample ViewModel property; this property is used in the view to display its value using a Binding. 
    /// </summary> 
    /// <returns></returns> 
    [DataMember] 
    public string ContentShort 
    { 
     get 
     { 
      return _contentshort; 
     } 
     set 
     { 
      if (value != _contentshort) 
      { 
       _contentshort = value; 
       NotifyPropertyChanged("ContentShort"); 
      } 
     } 
    } 

    private string _imageUrl; 
    /// <summary> 
    /// Sample ViewModel property; this property is used in the view to display its value using a Binding. 
    /// </summary> 
    /// <returns></returns> 
    [DataMember] 
    public string ImageUrl 
    { 
     get 
     { 
      return _imageUrl; 
     } 
     set 
     { 
      if (value != _imageUrl) 
      { 
       _imageUrl = value; 
       NotifyPropertyChanged("ImageUrl"); 
      } 
     } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 
    private void NotifyPropertyChanged(String propertyName) 
    { 
     PropertyChangedEventHandler handler = PropertyChanged; 
     if (null != handler) 
     { 
      handler(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 
} 

服務代理,其提取的數據是這樣的:

public class ServiceAgent 
{ 
    public delegate void SocialListItemsLoadedEventHandler(ObservableCollection<SocialListItemViewModel> socialItems); 
    public event SocialListItemsLoadedEventHandler SocialItemsLoaded; 

    private ObservableCollection<SocialListItemViewModel> socialListItemViewModels = new ObservableCollection<SocialListItemViewModel>(); 
    public void GetSocialItems() 
    { 
     WebClient wcNewsTractor = new WebClient(); 
     wcNewsTractor.DownloadStringCompleted += new DownloadStringCompletedEventHandler(wcNewsTractor_DownloadStringCompleted); 
     wcNewsTractor.DownloadStringAsync(new Uri("URL TO JSON FEED")); 

    } 

    void wcNewsTractor_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e) 
    { 
     if (e.Error == null && e.Cancelled == false) 
     { 
      //ObservableCollection<SocialListItemViewModel> socialListItemViewModels = new ObservableCollection<SocialListItemViewModel>(); 

      ThreadPool.QueueUserWorkItem((s) => 
      { 
      socialListItemViewModels = ReadToObject(e.Result); 
      Deployment.Current.Dispatcher.BeginInvoke(() => 
                  { 
                   SocialItemsLoaded(socialListItemViewModels); 
                  }); 

      }); 

     } 
    } 

    // Deserialize a JSON stream to a User object. 
    public static ObservableCollection<SocialListItemViewModel> ReadToObject(string json) 
    { 
     ObservableCollection<SocialListItemViewModel> res = new ObservableCollection<SocialListItemViewModel>(); 
     List<SocialListItemViewModel> deserializedItems = new List<SocialListItemViewModel>(); 
     MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(json)); 
     DataContractJsonSerializer ser = new DataContractJsonSerializer(deserializedItems.GetType()); 
     deserializedItems = ser.ReadObject(ms) as List<SocialListItemViewModel>; 
     ms.Close(); 
     return new ObservableCollection<SocialListItemViewModel>(deserializedItems); 
    } 
} 

在我的MainPage中,構造函數如下所示:

public partial class MainPage : PhoneApplicationPage 
    { 
     // Constructor 
     public MainPage() 
     { 
      InitializeComponent(); 

      // Set the data context of the listbox control to the sample data 
      DataContext = new SocialListItemViewModel(); //App.ViewModel; 
      this.Loaded += new RoutedEventHandler(MainPage_Loaded); 
     } 

MainPage.xaml中出增加了模板看起來是這樣的:

 <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> 
     <ListBox x:Name="MainListBox" Margin="0,0,-12,0" ItemsSource="{Binding Items}" SelectionChanged="MainListBox_SelectionChanged" ItemContainerStyle="{StaticResource ListBoxItemStyle1}"> 
      <ListBox.ItemTemplate> 
       <DataTemplate> 
        <StackPanel Margin="0,0,0,17" Width="432" Height="225" d:DataContext="{d:DesignData /SampleData/SocialListItemViewModelSampleData1.xaml}"> 
         <Image Height="125" Width="125" Margin="0" Source="http://myimage.com/myimage.jpg" HorizontalAlignment="Left" VerticalAlignment="Center"/> 
         <TextBlock x:Name="ContentShort" Text="{Binding ContentShort}" TextWrapping="Wrap" Margin="0,-125,0,0" Style="{StaticResource PhoneTextSubtleStyle}" HorizontalAlignment="Right" Foreground="#99FFFFFF" Width="279" RenderTransformOrigin="0.459,0.513" VerticalAlignment="Center" Height="160"/> 
         <Button Name="btnVote" Height="72" HorizontalAlignment="Center" Width="225" Margin="0,-10,-130,0" VerticalAlignment="Center" BorderThickness="2" Content="Vote" Background="#FF0090A1" /> 
        </StackPanel> 
       </DataTemplate> 
      </ListBox.ItemTemplate> 
     </ListBox> 
    </Grid> 
+0

你是如何分配你的視圖模型的視圖(例如,你在哪裏設置的DataContext) ? - 另外,請顯示相關的xaml。 – Robaticus

+0

嗨Robaticus,我使用標準的「Windows Phone Databound應用程序」作爲模板。我已將MainPage中的上下文更改爲我的視圖模型SocialListItem。 – Dofs

回答

1

好吧,我認爲很可能將在這裏,你是不是你的射擊通知的的ObservableCollection Items

在這一行:

Deployment.Current.Dispatcher.BeginInvoke(() => 
         { 
          this.Items = socialItems; 

你拋出你的舊的ObservableCollection,並將其分配給從服務返回的一個。 ObservableCollection只發送有關添加/刪除的通知,所以當你這樣做的時候,沒有什麼東西被激發到視圖。

有兩種解決方法。一種是用私人支持成員變量設置Items,並在調用者中調用NotifyPropertyChanged("Items")。另外,您也可以返回一個通用List<>,並通過內容迭代,將其添加到Items集合,這樣的事情:

Deployment.Current.Dispatcher.BeginInvoke(() => 
         { 
          this.Items.Clear(); 
          foreach(var item in socialItems) 
          { 
           this.Items.Add(item); 
          } 
         } 
+0

這是有道理的。綁定連接在列表中。清除列表並手動調用NotifyPropertyChanged都起作用。非常感謝! – Dofs

+1

很高興幫助。 DataBinding起初可能比較棘手,但它很快就會成爲你最好的朋友。 – Robaticus

相關問題