私は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>