c# - 显示来自 JSON 文件的组标题列表

标签 c# xaml windows-phone-8.1

我有一个小问题,我已经研究了几天。

我正在使用 Pivot 模板在 Windows Phone 上编写一个小型应用程序。 我想在一个 JSON 文件组的列表标题中显示,在设计器中它工作正常,就像这样:

enter image description here

但是当我在手机上试用该应用程序时,没有任何显示,Visual Studio 向我发送以下错误:

Error: BindingExpression path error: 'Groups' property not found on 'Simapp.Data.SampleDataGroup, Simapp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'. BindingExpression: Path='Groups' DataItem='Simapp.Data.SampleDataGroup, Simapp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'; target element is 'Windows.UI.Xaml.Controls.ListView' (Name='null'); target property is 'ItemsSource' (type 'Object')

我使用的文件如下:

Json: pastebin.com/hVfwYbaf 
Xaml : pastebin.com/0G2hPG6i (also see below)
Code : pastebin.com/Ftnx0g6g (also see below)

Xaml:

<Pivot x:Uid="Pivot" Title="SIMAPP" x:Name="pivot" CommonNavigationTransitionInfo.IsStaggerElement="True">
    <!--Pivot item one-->
    <PivotItem
        x:Uid="PivotItem1"
        Margin="19,14.5,0,0"
        Header="Reader"
        Loaded="SecondPivot_Loaded"
        DataContext="{Binding FirstGroup}"
       d:DataContext="{Binding Source={d:DesignData Source=/DataModel/SampleData.json, Type=data:SampleDataSource}}"
        CommonNavigationTransitionInfo.IsStaggerElement="True">

        <!--Double line list with text wrapping-->
        <ListView
            ItemsSource="{Binding Groups}"
                                Loaded="SecondPivot_Loaded"

            ContinuumNavigationTransitionInfo.ExitElementContainer="True">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <StackPanel Margin="0,0,0,9.5">
                        <!--Error: BindingExpression path error: 'Groups' property not found on 'Simapp.Data.SampleDataGroup, Simapp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'. BindingExpression: Path='Groups' DataItem='Simapp.Data.SampleDataGroup, Simapp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'; target element is 'Windows.UI.Xaml.Controls.ListView' (Name='null'); target property is 'ItemsSource' (type 'Object')-->

                        <TextBlock

                            Text="{Binding Title}"
                            TextWrapping="Wrap"
                            Pivot.SlideInAnimationGroup="1"
                            CommonNavigationTransitionInfo.IsStaggerElement="True"
                            Style="{ThemeResource ListViewItemTextBlockStyle}"
                            Margin="0,0,19,0"/>
                        <TextBlock
                            Text="{Binding Description}"
                            TextWrapping="WrapWholeWords"
                            Pivot.SlideInAnimationGroup="2"
                            CommonNavigationTransitionInfo.IsStaggerElement="True"
                            Style="{ThemeResource ListViewItemContentTextBlockStyle}"
                            Margin="0,0,19,0"/>
                    </StackPanel>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </PivotItem>
</Pivot>

代码

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;
using Windows.Data.Json;
using Windows.Storage;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Imaging;

namespace Simapp.Data
{
    public class SampleDataItem
    {
        public SampleDataItem(String uniqueId, String title, String subtitle, String imagePath, String description, String content)
        {
            this.UniqueId = uniqueId;
            this.Title = title;
            this.Subtitle = subtitle;
            this.Description = description;
            this.ImagePath = imagePath;
            this.Content = content;
        }

        public string UniqueId { get; private set; }
        public string Title { get; private set; }
        public string Subtitle { get; private set; }
        public string ImagePath { get; private set; }
        public string Description { get; private set; }
        public string Content { get; private set; }

        public override string ToString()
        {
            return this.Title;
        }
    }

    public class SampleDataGroup
    {
        public SampleDataGroup(String uniqueId, String title, String subtitle, String imagePath, String description)
        {
            this.UniqueId = uniqueId;
            this.Title = title;
            this.Subtitle = subtitle;
            this.Description = description;
            this.ImagePath = imagePath;
            this.Items = new ObservableCollection<SampleDataItem>();
        }

        public string UniqueId { get; private set; }
        public string Title { get; private set; }
        public string Subtitle { get; private set; }
        public string ImagePath { get; private set; }
        public string Description { get; private set; }
        public ObservableCollection<SampleDataItem> Items { get; private set; }

        public override string ToString()
        {
            return this.Title;
        }
    }

    public sealed class SampleDataSource
    {
        private static SampleDataSource _sampleDataSource = new SampleDataSource();

        private ObservableCollection<SampleDataGroup> _groups = new ObservableCollection<SampleDataGroup>();
        public ObservableCollection<SampleDataGroup> Groups
        {
            get { return this._groups; }
        }

        public static async Task<IEnumerable<SampleDataGroup>> GetGroupsAsync()
        {
            await _sampleDataSource.GetSampleDataAsync();

            return _sampleDataSource.Groups;
        }

        public static async Task<SampleDataGroup> GetGroupAsync(string uniqueId)
        {
            await _sampleDataSource.GetSampleDataAsync();
            // Simple linear search is acceptable for small data sets
            var matches = _sampleDataSource.Groups.Where((group) => group.UniqueId.Equals(uniqueId));
            if (matches.Count() == 1) return matches.First();
            return null;
        }

        public static async Task<SampleDataItem> GetItemAsync(string uniqueId)
        {
            await _sampleDataSource.GetSampleDataAsync();
            // Simple linear search is acceptable for small data sets
            var matches = _sampleDataSource.Groups.SelectMany(group => group.Items).Where((item) => item.UniqueId.Equals(uniqueId));
            if (matches.Count() == 1) return matches.First();
            return null;
        }

        private async Task GetSampleDataAsync()
        {
            if (this._groups.Count != 0)
                return;

            Uri dataUri = new Uri("ms-appx:///DataModel/SampleData.json");

            StorageFile file = await StorageFile.GetFileFromApplicationUriAsync(dataUri);
            string jsonText = await FileIO.ReadTextAsync(file);
            JsonObject jsonObject = JsonObject.Parse(jsonText);
            JsonArray jsonArray = jsonObject["Groups"].GetArray();
            int count = 0;

            foreach (JsonValue groupValue in jsonArray)
            {
                JsonObject groupObject = groupValue.GetObject();
                SampleDataGroup group = new SampleDataGroup(groupObject["UniqueId"].GetString(),
                                                            groupObject["Title"].GetString(),
                                                            groupObject["Subtitle"].GetString(),
                                                            groupObject["ImagePath"].GetString(),
                                                            groupObject["Description"].GetString());


                foreach (JsonValue itemValue in groupObject["Items"].GetArray())
                {
                    JsonObject itemObject = itemValue.GetObject();
                    group.Items.Add(new SampleDataItem(itemObject["UniqueId"].GetString(),
                                                       itemObject["Title"].GetString(),
                                                       itemObject["Subtitle"].GetString(),
                                                       itemObject["ImagePath"].GetString(),
                                                       itemObject["Description"].GetString(),
                                                       itemObject["Content"].GetString()));
                }
                this.Groups.Add(group);
            } 
        }
    }
}

我猜问题是组标题的路径错误,但我不知道如何更正。

最好的问候

最佳答案

我注意到您从 Visual Studio 中的默认 Pivot 应用程序模板 开始,这使得调试和帮助变得更加容易(下次,只需在您的问题中提及它 :))。

您的代码中的问题区域如下:

<PivotItem
    x:Uid="PivotItem1"
    Margin="19,14.5,0,0"
    Header="Reader"
    Loaded="SecondPivot_Loaded"
    DataContext="{Binding FirstGroup}"
    d:DataContext="{Binding Source={d:DesignData Source=/DataModel/SampleData.json, Type=data:SampleDataSource}}"
    CommonNavigationTransitionInfo.IsStaggerElement="True">

    <!--Double line list with text wrapping-->
    <ListView
        ItemsSource="{Binding Groups}"

DataContext 保存在 PivotItem 上(这是一个单独的组项)并更改包含 ItemsSource ListViewItems(组中的属性)到 Groups(组中没有属性)。要了解 FirstGroup 属性中的内容,只需检查 PivotPage.xaml.cs 中的代码即可。

var sampleDataGroup = await SampleDataSource.GetGroupAsync("Group-1");
this.DefaultViewModel[FirstGroupName] = sampleDataGroup;

如果您想更改示例以显示组而不是项目,则必须更新 XAML 和背后的代码以获取数据。

XAML:

<PivotItem
            x:Uid="PivotItem1"
            Margin="19,14.5,0,0"
            Header="first"
            DataContext="{Binding AllGroups}"
            d:DataContext="{Binding Groups, Source={d:DesignData Source=/DataModel/SampleData.json, Type=data:SampleDataSource}}"
            CommonNavigationTransitionInfo.IsStaggerElement="True">
            <!--Double line list with text wrapping-->
            <ListView
                ItemsSource="{Binding}"

代码:

var sampleDataGroups = await SampleDataSource.GetGroupsAsync(); // all groups
this.DefaultViewModel["AllGroups"] = sampleDataGroups;

请注意,我在旧 key FirstGroup 旁边引入了一个新 key AllGroups。另请注意,ListView 现在包含一组组而不是项目,因此下一步将更新单击项目时的事件处理程序(流程的其余部分等)。

private void ItemView_ItemClick(object sender, ItemClickEventArgs e)
{
    //var itemId = ((SampleDataItem)e.ClickedItem).UniqueId;
    var itemId = ((SampleDataGroup)e.ClickedItem).UniqueId;
    if (!Frame.Navigate(typeof(ItemPage), itemId))
    {
        throw new Exception(this.resourceLoader.GetString("NavigationFailedExceptionMessage"));
    }
}

关于c# - 显示来自 JSON 文件的组标题列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34467517/

相关文章:

windows-phone-8.1 - 如何向 Windows Phone 8.1 RT 应用程序中的控件添加倾斜效果?

c# - 如何处理http链接?

c# - 仅使用 C#/.NET 重命名 .Zip 条目?

c# - 用于显示程序集名称的数据绑定(bind)

c# - WinRT 中 ViewModel 层的虚拟化

c# - 在 Windows Phone 8.1 应用程序中导航回主页会导致异常

c# - 从 SQL Server 查询将数据导入 Excel

c# - 如何在 C# 中模拟另一个用户进行 DCOM 连接?

c# - 此 C# 的等效 XAML 行

c# - Silverlight 按钮 Mouse Over 类似悬停效果