2011-12-20 5 views
0

Я относительно новичок в C#, silverlight и всей парадигме привязки данных. Я работал над небольшим тестовым приложением, которое извлекает данные из reddit через их API с помощью Json.Net. В любом случае, я получаю данные в своем приложении просто отлично, но теперь у меня возникают проблемы с нажатием данных в пользовательском интерфейсе. Я пробовал несколько разных конфигураций безрезультатно. В любом случае, код находится здесь:DataBinding deserialized json array

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."; 
     }); 
    } 

Это основная часть моего кода. Остальные классы здесь, и они предназначены для десериализации JSON, предоставляемого reddit API.

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; } 
    }  
} 

Допустим, что материал XAML UI выглядит следующим образом

  <ListBox> 
      <ListBox.ItemTemplate> 
       <DataTemplate> 
        <StackPanel> 
         <TextBlock x:Name="TitleInfo" /> 
         <TextBlock x:Name="AuthorInfo" /> 
        </StackPanel> 
       </DataTemplate> 
      </ListBox.ItemTemplate> 
     </ListBox> 

Названия содержатся внутри экземпляра RootObject называется тема. Таким образом, способ захватить названия будет

topic.data.children[0].data.title; 

Однако я почти не знаю, как я могу связать, что эти текстовые поля или listbox..I знать DataContext должен быть установлен и эти элементы могут быть переплетены через код в отличие от xaml, но я не могу найти какой-либо изящный способ сделать это. Любая помощь? Благодаря тонну.

ответ

1

Вы почти здесь, из-за внешнего вида вещей. Ваша проблема заключается в том, что вы пытаетесь установить DataContext всей страницы как один заголовок из одной записи (this.DataContext = topic.data.children[0].data.title;) - это, вероятно, не то, что вы хотите сделать ...

Чтобы получить данные в своем ListBox, у вас есть 2 варианта - вы можете явно установить ItemsSource из ListBox, как так

myListBox.ItemsSource = topic.data.children; 

, а затем обновить код XAML, чтобы показать данные с этой точки в графе объектов ...

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

Однако , если вы хотите использовать данные в другом месте в t он, вы, вероятно, захотите установить DataContext для всей страницы.

DataContext = topic; 

и установить XAML на ListBox к чему-то немного другому ...

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

Надеется, что это помогает.

+0

Это в значительной степени именно то, что я искал. То, как я пытался определить контекст данных, не предназначалось для публикации здесь, это было скорее удар в темноте, который я знал, вероятно, не сработал и забыл удалить. В любом случае, я изучил привязку данных к таким примерам, но ничего не нашел. Он работает отлично. Благодарю. – Wilcoholic

0

Было бы лучше реализовать шаблон MVVM, если вы хотите иметь дело с DataBinidng.

В то же время, здесь исправление вашего примера:

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); 
     } 
    } 
} 

И обновленный 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> 
+0

Я посмотрю MVVM, спасибо за ссылку. – Wilcoholic

Смежные вопросы