0

私はWindowsPhoneアプリケーションの作成をいじっています。私はこのチュートリアルを見てきましたが、ビューがデータで更新されないという問題があります(テンプレートは単に空です)。

アイテムコレクションが実際にデータで設定されていることを確認しましたが、正しく発生しないのは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は、追加/削除に関する通知のみを送信するため、これを行うと、ビューに対して何も起動されません。

これを修正するには2つの方法があります。1つは、プライベートバッキングメンバー変数を設定し、セッターItemsを呼び出すことです。NotifyPropertyChanged("Items")または、ジェネリックを返し、List<>コンテンツを反復処理して、次のItemsようにコレクションに追加することもできます。

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