【问题标题】:UWP Databinding from JSON not working来自 JSON 的 UWP 数据绑定不起作用
【发布时间】:2016-08-09 09:54:19
【问题描述】:

我正在尝试使用 JSON.NET 从 json url 填充网格。我已经能够反序列化来自 url 的数据并将其绑定到模型类。但是,它不绑定到 XAML 页面。 这是我的模型类和 MovieManger 类:

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;

namespace DataBindingTest3.Models
{
    public class AmgMovie
    {
        public string state { get; set; }
        public Data data { get; set; }
    }
    public class Data
    {
        public int type { get; set; }
        public string type_name { get; set; }
        public Movie[] movies { get; set; }
    }

    public class Movie
    {
        public string id { get; set; }
        public string title { get; set; }
        public string movie_desc { get; set; }
        public string movie_actors { get; set; }
        public string movie_director { get; set; }
        public string music_director { get; set; }
        public string movie_year { get; set; }
        public string movie_month { get; set; }
        public string realeased_date { get; set; }
        public string image { get; set; }
        public string portrait_image { get; set; }
        public string movie_list_image_url { get; set; }
        public string movie_poster_url { get; set; }
        public string duration { get; set; }
        public string url { get; set; }
        public string download_url { get; set; }
        public string trailer_url { get; set; }
        public int allow_download { get; set; }
    }

    public class MovieManager
    {
        public static async Task<List<Movie>> GetMovies()
        {
            var movies = new List<Movie>();
            var amg = new HttpClient();
            HttpResponseMessage response = await amg.GetAsync(new Uri("some URL"));
            var json = await response.Content.ReadAsStringAsync();
            AmgMovie Movie = JsonConvert.DeserializeObject<AmgMovie>(json);

            for (uint i = 0; i < Movie.data.movies.Count(); i++)
            {
                string id1 = Movie.data.movies[i].id;
                string title1 = Movie.data.movies[i].title;
                string portrait_image1 = Movie.data.movies[i].portrait_image;

                movies.Add(new Movie { id = id1, title = title1, portrait_image = portrait_image1 });
            }

            return movies;

        }
    }
}

这是 XAML 页面的代码:

public sealed partial class MainPage : Page
    {
        private List<Movie> Movie;
        public MainPage()
        {
            this.InitializeComponent();
        }

        private async void Page_Loaded(object sender, RoutedEventArgs e)
        {
            Movie = await MovieManager.GetMovies();
        }
    }

这是 XAML 页面标记:

<Page
    x:Class="DataBindingTest3.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:DataBindingTest3"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:data="using:DataBindingTest3.Models"
    Loaded="Page_Loaded"
    mc:Ignorable="d">

    <Page.Resources>
        <DataTemplate x:DataType="data:Movie" x:Key="MovieDataTemplate">
            <StackPanel>
                <TextBlock x:Name="movieID" Text="{x:Bind id}" FontSize="12" Foreground="Black" />
                <Image x:Name="moviePoster" Source="{x:Bind portrait_image}" Width="145" Height="214"/>
                <TextBlock x:Name="movieName" Text="{x:Bind title}" FontSize="16" Foreground="Black"/>
            </StackPanel>
        </DataTemplate>
    </Page.Resources>
    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="100" />
        </Grid.RowDefinitions>

        <GridView Grid.Row="0" ItemsSource="{x:Bind Movie}" ItemTemplate="{StaticResource MovieDataTemplate}">

        </GridView>

    </Grid>
</Page>

我还尝试了不使用 json 的绑定,并且只是在 MovieManager 类中输入了一些示例数据,它完美地绑定了。我注意到在调试示例方法和 json 方法时,这两种方法都会返回数据,但是只有当我使用示例数据时,调试器才会在 XAML Page.g.cs 中绑定数据。

【问题讨论】:

    标签: c# json xaml uwp uwp-xaml


    【解决方案1】:

    你有两个选择:

    1. 在 MainPage.xaml.cs 中将 Movie 字段的类型更改为 observable 集合,并将 GetMovies() 函数的结果项复制到集合中,如下所示: ))

      private ObservableCollection<Movie> Movies = new ObservableCollection<Movie>();
      
      private async void AboutPage_Loaded(object sender, RoutedEventArgs e)
      {
          foreach (var movie in await GetMovies())
          {
              Movie.Add(movie);
          }
      }
      
    2. 您使用 INotifyPropertyChanged 实现为 Movies List 创建一个属性,并将 x:Bind 模式更改为 OneWay:(如果 Movies 属性更改(而不是其内容),则 UI 更改)

      public sealed partial class MainPage : Page, INotifyPropertyChanged
      {
          public event PropertyChangedEventHandler PropertyChanged;
      
          private List<Movie> _movies;
          public List<Movie> Movies
          {
              get { return _movies; }
              set { if(value != _movies) { _movies = value; PropertyChanged?.Invoke(nameof(Movies)); } }
          }
      
          public MainPage()
          {
              this.InitializeComponent();
          }
      
          private async void Page_Loaded(object sender, RoutedEventArgs e)
          {
              Movies = await MovieManager.GetMovies();
          }
      }
      

      Xaml:

      <GridView Grid.Row="0" ItemsSource="{x:Bind Movies, Mode=OneWay}" ItemTemplate="{StaticResource MovieDataTemplate}" />
      

    在第一个版本中,如果您用新列表覆盖电影,用户界面不会改变。 在第二个版本中,如果您向列表中添加/删除元素,UI 不会改变。

    您可以将这两个版本结合起来。

    【讨论】:

      【解决方案2】:

      您需要将 Movie 集合设为 ObservableCollection 而不仅仅是 List。

      【讨论】:

      • 嗨,我尝试将其更改为 ObservableCollection。没有编译错误。也不行。
      猜你喜欢
      • 2016-11-18
      • 2018-03-15
      • 2019-04-30
      • 1970-01-01
      • 2018-07-26
      • 2019-01-28
      • 1970-01-01
      • 2017-08-06
      • 1970-01-01
      相关资源
      最近更新 更多