Привязка данных десериализованный массив JSON - PullRequest
0 голосов
/ 20 декабря 2011

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

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, который предоставляет API Reddit.

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 выглядит следующим образом

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

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

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

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

Ответы [ 2 ]

1 голос
/ 20 декабря 2011

Ты почти там, судя по всему. Ваша проблема в том, что вы пытаетесь задать для 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>

Однако, если вы хотите использовать данные в другом месте страницы, вы, вероятно, захотите установить 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 голосов
/ 20 декабря 2011

Было бы лучше реализовать шаблон 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>
...