0

我正在玩创建一个 Windows Phone 应用程序。我一直在看这个教程,但我遇到了一些问题,即视图没有用数据更新(模板只是空的)。

我已确保项目集合实际上是用数据设置的,但我怀疑它是 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>
4

1 回答 1

1

好的,我认为这里可能发生的事情是您没有触发 ObservableCollection 的通知Items

在这一行:

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

您正在丢弃旧的 ObservableCollection,并将其分配给从您的服务返回的那个。ObservableCollection 仅在添加/删除时发送通知,因此当您执行此操作时,视图不会触发任何内容。

你有两种方法可以解决这个问题。一种是设置Items一个私有的后备成员变量,并NotifyPropertyChanged("Items")在 setter 中调用。或者,您可以返回一个 generic List<>,并遍历内容,将它们添加到Items集合中,如下所示:

 Deployment.Current.Dispatcher.BeginInvoke(() =>
                       {
                           this.Items.Clear();
                           foreach(var item in socialItems)
                           {
                                this.Items.Add(item);
                           }
                       }
于 2012-05-14T01:36:20.293 回答