DataBinding反序列化json数组

发布于 2024-12-22 05:14:15 字数 5024 浏览 2 评论 0原文

我对 C#、silverlight 和整个数据绑定范例相对较新。我一直在开发一个小测试应用程序,它使用 Json 通过 API 从 reddit 提取数据。网。不管怎样,我将数据很好地导入到我的应用程序中,但现在我在将数据推送到 UI 时遇到了麻烦。我尝试了几种不同的配置,但均无济于事。无论如何,代码在这里:

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

这是我的代码的主要部分。其余的类在这里,它们用于 reddit API 提供的 JSON 的反序列化。

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>

标题包含在名为 topic 的 RootObject 实例内。因此,获取标题的方法是

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

但是,我几乎不知道如何将其绑定到这些文本框或列表框。我知道必须设置数据上下文,并且可以通过代码而不是 xaml 绑定这些项目,但我想不出任何优雅的方法来做到这一点。有什么帮助吗?非常感谢。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

ζ澈沫 2024-12-29 05:14:15

从表面上看,你已经快到了。您的问题是您试图将整个页面的 DataContext 设置为一条记录中的单个标题 (this.DataContext = topic.data.children[0].data.title; ) -这可能不是您想要做的...

要将数据放入 ListBox,您有 2 个选项 - 您可以像这样显式设置 ListBox 的 ItemsSource

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;  

并将 ListBox 上的 XAML 设置为稍微不同的内容...

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

希望这会有所帮助。

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.

香橙ぽ 2024-12-29 05:14:15

如果你想处理DataBinidng,最好实现 MVVM 模式。

同时,这里是您的示例的修复:

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>

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>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文