Reputation:
I am relatively new to C#, silverlight and the whole data binding paradigm. I have been working on a little test app that pulls data from reddit via their API using Json.Net. Anyways, I get the data into my application just fine, but now I am having trouble with pushing the data into the UI. I have tried several different configurations to no avail. Anyways, the code is here:
public partial class MainPage : PhoneApplicationPage
{
string json = "";
RootObject topic { get; set; }
public MainPage()
{
InitializeComponent();
}
private void button1_Click(object sender, RoutedEventArgs e)
{
textBlock1.Text = "Retrieving...";
string url = @"http://www.reddit.com/r/all.json";
HttpWebRequest hWebRequest = (HttpWebRequest)HttpWebRequest.Create(url);
hWebRequest.Method = "GET";
hWebRequest.BeginGetResponse(Response_Completed, hWebRequest);
}
public void Response_Completed(IAsyncResult result)
{
HttpWebRequest request = (HttpWebRequest)result.AsyncState;
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(result);
using (StreamReader streamReader = new StreamReader(response.GetResponseStream()))
{
json = streamReader.ReadToEnd();
topic = JsonConvert.DeserializeObject<RootObject>(json);
}
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
this.DataContext = topic.data.children[0].data.title;
textBlock1.Text = "Done.";
});
}
That is the main part of my code. The remaining classes are here, and they are for the deserialization of the JSON the reddit API provides.
public class MediaEmbed
{
public string content { get; set; }
public int? width { get; set; }
public bool? scrolling { get; set; }
public int? height { get; set; }
}
public class Oembed
{
public string provider_url { get; set; }
public string description { get; set; }
public string title { get; set; }
public string url { get; set; }
public string author_name { get; set; }
public int height { get; set; }
public int width { get; set; }
public string html { get; set; }
public int thumbnail_width { get; set; }
public string version { get; set; }
public string provider_name { get; set; }
public string thumbnail_url { get; set; }
public string type { get; set; }
public int thumbnail_height { get; set; }
public string author_url { get; set; }
}
public class Media
{
public string type { get; set; }
public Oembed oembed { get; set; }
}
public class Data2
{
public string domain { get; set; }
public MediaEmbed media_embed { get; set; }
public object levenshtein { get; set; }
public string subreddit { get; set; }
public string selftext_html { get; set; }
public string selftext { get; set; }
public object likes { get; set; }
public bool saved { get; set; }
public string id { get; set; }
public bool clicked { get; set; }
public string title { get; set; }
public Media media { get; set; }
public int score { get; set; }
public bool over_18 { get; set; }
public bool hidden { get; set; }
public string thumbnail { get; set; }
public string subreddit_id { get; set; }
public string author_flair_css_class { get; set; }
public int downs { get; set; }
public bool is_self { get; set; }
public string permalink { get; set; }
public string name { get; set; }
public double created { get; set; }
public string url { get; set; }
public string author_flair_text { get; set; }
public string author { get; set; }
public double created_utc { get; set; }
public int num_comments { get; set; }
public int ups { get; set; }
}
public class Child
{
public string kind { get; set; }
public Data2 data { get; set; }
}
public class Data
{
public string modhash { get; set; }
public Child[] children { get; set; }
public string after { get; set; }
public object before { get; set; }
}
public class RootObject
{
public string kind { get; set; }
public Data data { get; set; }
}
}
Let's say that the XAML UI stuff looks like this
<ListBox>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock x:Name="TitleInfo" />
<TextBlock x:Name="AuthorInfo" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
The titles are contained inside of the instance of RootObject called topic. So the way to grab the titles would be
topic.data.children[0].data.title;
However, I have almost no idea how I can bind that to these text boxes or a listbox..I know a datacontext must be set and these items can be binded via code as opposed to xaml, but I can't figure out any elegant way to do this. Any help? Thanks a ton.
Upvotes: 0
Views: 2515
Reputation: 29953
You're almost there, from the looks of things. Your issue is that you are trying to set the DataContext of the whole page to be a single title from one record (this.DataContext = topic.data.children[0].data.title;
) - that's probably not what you mean to do...
To get the data into your ListBox, you have 2 options - you can explicitly set the ItemsSource of the ListBox like so
myListBox.ItemsSource = topic.data.children;
and then update the XAML to show the data from that point in the object graph...
<ListBox Name="MyListBox">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock x:Name="TitleInfo" Text="{Binding data.title}" />
<TextBlock x:Name="AuthorInfo" Text="{Binding data.author}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
However, if you are looking to use data elsewhere in the page, you will probably want to set the DataContext for the whole page.
DataContext = topic;
and set your XAML on the ListBox to something slightly different...
<ListBox Name="MyListBox" ItemsSource="{Binding data.children}" >
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock x:Name="TitleInfo" Text="{Binding data.title}" />
<TextBlock x:Name="AuthorInfo" Text="{Binding data.author}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Hope this helps.
Upvotes: 1
Reputation: 970
It would be better to implement MVVM pattern if you want to deal with DataBinidng.
In the meantime, here is a fix of your example:
public partial class MainPage : PhoneApplicationPage, INotifyPropertyChanged
{
string json = "";
private RootObject topic;
public event PropertyChangedEventHandler PropertyChanged;
public RootObject Topic
{
get
{
return this.topic;
}
set
{
this.topic = value;
var handler = this.PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs("Topic"));
}
}
}
public MainPage()
{
InitializeComponent();
this.DataContext = this;
}
private void button1_Click(object sender, RoutedEventArgs e)
{
...
}
public void Response_Completed(IAsyncResult result)
{
HttpWebRequest request = (HttpWebRequest)result.AsyncState;
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(result);
using (StreamReader streamReader = new StreamReader(response.GetResponseStream()))
{
json = streamReader.ReadToEnd();
this.Topic = JsonConvert.DeserializeObject<RootObject>(json);
}
}
}
And an updated xaml:
<ListBox Name="MyListBox" ItemsSource="{Binding Topic.data.children}" >
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock x:Name="TitleInfo" Text="{Binding data.title}" />
<TextBlock x:Name="AuthorInfo" Text="{Binding data.author}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Upvotes: 0