简体   繁体   English

将Observable Collection绑定到GridView

[英]Binding an Observable Collection to a GridView

My UWP is required to have a Favorites page that allows the user to reorder and save the data on the page. 我的UWP需要有一个“收藏夹”页面,允许用户重新排序并保存页面上的数据。 Originally my data comes from a large JSON file which is deserialized using Newtonsoft's Json.net, and is stored for this page in a Dictionary which then fills the public ObservableCollection. 最初我的数据来自一个大型JSON文件,它使用Newtonsoft的Json.net进行反序列化,并在此字典中存储在一个字典中,然后填充公共ObservableCollection。

This is where I now get lost, setting the ObservableCollection as the DataContext and then using the data as a Binding in the XAML code to populate the GridView with all the Titles, Subtitles and Images that each Item requires. 这就是我现在迷失的地方,将ObservableCollection设置为DataContext,然后在XAML代码中使用数据作为Binding,使用每个Item所需的所有标题,字幕和图像填充GridView。 In theory this should work, but in my trials and tests the page remains blank while all the C# code behind the scenes makes it seem like it should be populated. 理论上这应该可以工作,但是在我的试验和测试中,页面仍然是空白的,而幕后的所有C#代码似乎都应该填充它。

I don't know why the page is not filling to I am turning to the collective help of all of you. 我不知道为什么页面不适合我转向你们所有人的集体帮助。

PS: I don't really care about the neatness of this code, I just want to get it working. PS:我真的不关心这段代码的整洁,我只是想让它运转起来。


XAML File XAML文件

<Page
x:Name="pageRoot"
x:Class="Melbourne_Getaway.FavouritesPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Melbourne_Getaway"
xmlns:data="using:Melbourne_Getaway.Data"
xmlns:common="using:Melbourne_Getaway.Common"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">

<Page.Resources>
    <x:String x:Key="AppName">Favourites</x:String>
</Page.Resources>

<!--
    This grid acts as a root panel for the page that defines two rows:
    * Row 0 contains the back button and page title
    * Row 1 contains the rest of the page layout
-->
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <Grid.ChildrenTransitions>
        <TransitionCollection>
            <EntranceThemeTransition />
        </TransitionCollection>
    </Grid.ChildrenTransitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="140" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>

    <GridView
        x:Name="itemGridView"
        AutomationProperties.AutomationId="ItemsGridView"
        AutomationProperties.Name="Items"
        TabIndex="1"
        Grid.RowSpan="2"
        Padding="60,136,116,46"
        SelectionMode="None"
        IsSwipeEnabled="false"
        CanReorderItems="True"
        CanDragItems="True"
        AllowDrop="True"
        ItemsSource="{Binding Items}">
        <GridView.ItemTemplate>
            <DataTemplate>
                <Grid HorizontalAlignment="Left" Width="250" Height="107">
                    <Border Background="{ThemeResource ListViewItemPlaceholderBackgroundThemeBrush}">
                        <Image Source="{Binding ImagePath}" Stretch="UniformToFill" AutomationProperties.Name="{Binding Title}" />
                    </Border>
                    <StackPanel VerticalAlignment="Bottom" Background="{ThemeResource ListViewItemOverlayBackgroundThemeBrush}">
                        <TextBlock Text="{Binding Title}" Foreground="{ThemeResource ListViewItemOverlayForegroundThemeBrush}" Style="{StaticResource BaseTextBlockStyle}" Height="30" Margin="15,0,15,0" FontWeight="SemiBold" />
                        <TextBlock Text="{Binding Group}" Foreground="{ThemeResource ListViewItemOverlaySecondaryForegroundThemeBrush}" Style="{StaticResource BaseTextBlockStyle}" TextWrapping="NoWrap" Margin="15,-15,15,10" FontSize="12" />
                    </StackPanel>
                </Grid>
            </DataTemplate>
        </GridView.ItemTemplate>
    </GridView>

    <!-- Back button and page title -->
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="120" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <Button x:Name="backButton" Margin="39,59,39,0" Command="{Binding NavigationHelper.GoBackCommand, ElementName=pageRoot}"
                    Style="{StaticResource NavigationBackButtonNormalStyle}"
                    VerticalAlignment="Top"
                    AutomationProperties.Name="Back"
                    AutomationProperties.AutomationId="BackButton"
                    AutomationProperties.ItemType="Navigation Button" />
        <TextBlock x:Name="pageTitle" Text="{StaticResource AppName}" Style="{StaticResource HeaderTextBlockStyle}" Grid.Column="1"
                    IsHitTestVisible="false" TextWrapping="NoWrap" VerticalAlignment="Bottom" Margin="0,0,30,40" />
    </Grid>
</Grid>


CS File CS档案

using Melbourne_Getaway.Common;
using Melbourne_Getaway.Data;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using Windows.Storage;
using Windows.UI.Popups;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;

namespace Melbourne_Getaway
{
    public sealed partial class FavouritesPage : Page
    {
        public ObservableCollection<ItemData> Items { get; set; }

        private ObservableDictionary defaultViewModel = new ObservableDictionary();
        private NavigationHelper navigationHelper;
        private RootObject jsonLines;
        private StorageFile fileFavourites;
        private Dictionary<string, ItemData> ItemData = new Dictionary<string, ItemData>();

        public FavouritesPage()
        {
            loadJson();
            getFavFile();

            this.InitializeComponent();
            this.navigationHelper = new NavigationHelper(this);
            this.navigationHelper.LoadState += navigationHelper_LoadState;
        }

        private void setupObservableCollection()
        {
            Items = new ObservableCollection<ItemData>(ItemData.Values);
            DataContext = Items;
        }

        private async void loadJson()
        {
            var file = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///DataModel/SampleData.json"));
            string lines = await FileIO.ReadTextAsync(file);
            jsonLines = JsonConvert.DeserializeObject<RootObject>(lines);
            feedItems();
        }

        private async void getFavFile()
        {
            Windows.Storage.StorageFolder storageFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
            fileFavourites = await storageFolder.GetFileAsync("MelbGetaway.fav");
        }

        private async void feedItems()
        {
            if (await FileIO.ReadTextAsync(fileFavourites) != "")
            {
                foreach (var line in await FileIO.ReadLinesAsync(fileFavourites))
                {
                    foreach (var Group in jsonLines.Groups)
                    {
                        foreach (var Item in Group.Items)
                        {
                            if (Item.UniqueId == line)
                            {
                                var storage = new ItemData()
                                {
                                    Title = Item.Title,
                                    UniqueID = Item.UniqueId,
                                    ImagePath = Item.ImagePath,
                                    Group = Group.Title
                                };
                                ItemData.Add(storage.UniqueID, storage);
                            }
                        }
                    }
                }
            }
            else
            {//should only execute if favourites file is empty, first time use?
                foreach (var Group in jsonLines.Groups)
                {
                    foreach (var Item in Group.Items)
                    {
                        var storage = new ItemData()
                        {
                            Title = Item.Title,
                            UniqueID = Item.UniqueId,
                            ImagePath = Item.ImagePath,
                            Group = Group.Title
                        };
                        ItemData.Add(storage.UniqueID, storage);
                        await FileIO.AppendTextAsync(fileFavourites, Item.UniqueId + "\r\n");
                    }
                }
            }
            setupObservableCollection();
        }

        public ObservableDictionary DefaultViewModel
        {
            get { return this.defaultViewModel; }
        }

        #region NavigationHelper loader

        public NavigationHelper NavigationHelper
        {
            get { return this.navigationHelper; }
        }

        private async void MessageBox(string Message)
        {
            MessageDialog dialog = new MessageDialog(Message);
            await dialog.ShowAsync();
        }

        private async void navigationHelper_LoadState(object sender, LoadStateEventArgs e)
        {
            var sampleDataGroups = await SampleDataSource.GetGroupsAsync();
            this.defaultViewModel["Groups"] = sampleDataGroups;
        }

        #endregion NavigationHelper loader

        #region NavigationHelper registration

        protected override void OnNavigatedFrom(NavigationEventArgs e)
        {
            navigationHelper.OnNavigatedFrom(e);
        }

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            navigationHelper.OnNavigatedTo(e);
        }

        #endregion NavigationHelper registration
    }

    public class ItemData
    {
        public string UniqueID { get; set; }
        public string Title { get; set; }
        public string Group { get; set; }
        public string ImagePath { get; set; }
    }
}

Without a good Minimal, Complete, and Verifiable code example it is impossible to know for sure what's wrong. 如果没有一个好的Minimal,Complete和Verifiable代码示例 ,就不可能确定是什么问题。 However, one glaring error does appear in your code: 但是,您的代码中会出现一个明显的错误:

private void setupObservableCollection()
{
    Items = new ObservableCollection<ItemData>(ItemData.Values);
    DataContext = Items;
}

In your XAML, you bind to {Binding Items} . 在您的XAML中,绑定到{Binding Items} With the DataContext set to the Items property value, the correct binding would actually be just {Binding} . DataContext设置为Items属性值,正确的绑定实际上只是{Binding}

Alternatively, if you want to keep the XAML the way it is, you would have to set DataContext = this; 或者,如果你想保持XAML的方式,你必须设置DataContext = this; instead. 代替。 Of course, if you did it that way, then you would run into the problem that you don't appear to be raising INotifyPropertyChanged.PropertyChanged , or even implementing that interface. 当然,如果你这样做,那么你会遇到一个问题,你似乎没有提出INotifyPropertyChanged.PropertyChanged ,甚至实现该接口。 You can get away with that if you are sure the property will be set before the InitializeComponent() method is called, but in the code you've shown that does not appear to be the case. 如果您确定在调用InitializeComponent()方法之前设置了属性,那么您可以使用它,但在您显示的代码中似乎并非如此。

So if you want to set the binding to {Binding Items} you also need to implement INotifyPropertyChanged and make sure you raise the PropertyChanged event with the property name "Items" when you actually set the property. 因此,如果要将绑定设置为{Binding Items} ,还需要实现INotifyPropertyChanged ,并确保在实际设置属性时使用属性名称"Items"引发PropertyChanged事件。

If the above does not address your question, please improve the question by providing a good MCVE that reliably reproduces the problem. 如果上述问题无法解决您的问题,请通过提供可靠地再现问题的良好MCVE来改进问题。

I figured it out. 我想到了。 my problem lied in the way I was trying to pass the Data to the page itself. 我的问题在于我试图将数据传递给页面本身的方式。 Instead of using DataContext = Items; 而不是使用DataContext = Items; and trying to access the data that way. 并尝试以这种方式访问​​数据。 I instead set the direct ItemsSource for the GridView . 我改为为GridView设置直接的ItemsSource

The end result was simply changing DataContext = Items to itemGridView.ItemsSource = Items; 最终结果只是将DataContext = Items更改为itemGridView.ItemsSource = Items;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM