2016-07-30 4 views
1

내 UWP에는 사용자가 페이지의 데이터를 재정렬하고 저장할 수있는 즐겨 찾기 페이지가 있어야합니다. 원래 내 데이터는 Newtonsoft의 Json.net을 사용하여 직렬화 해제 된 대형 JSON 파일에서 가져온 것으로이 페이지에 대한 사전에 저장되어 ObservableCollection 공용을 채 웁니다.Observable 컬렉션을 GridView에 바인딩

ObservableCollection을 DataContext로 설정 한 다음 데이터를 XAML 코드의 바인딩으로 사용하여 각 항목에 필요한 모든 제목, 자막 및 이미지가있는 GridView를 채 웁니다. 이론 상으로는이 방법이 효과적 일지 모르지만, 시련과 테스트에서 페이지가 공백으로 남아있는 반면 배후에있는 모든 C# 코드는 채워 져야하는 것처럼 보입니다.

페이지가 채워지지 않는 이유를 모르겠습니다. 나는 여러분 모두의 집단적 도움에 의존하고 있습니다.

P.S :이 코드의 깔끔함에 대해서는별로 신경 쓰지 않아도되고 싶습니다.


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

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

답변

0

나는 그것을 알아 냈다. 내 문제는 내가 페이지 자체에 데이터를 전달하려는 방식으로 거짓말을했다. 대신 DataContext = Items;을 사용하고 그런 방식으로 데이터에 액세스하려고합니다. 대신 GridView에 대해 직접 ItemsSource을 설정했습니다.

최종 결과는 단순히 itemGridView.ItemsSource = Items;

0

없이 좋은 Minimal, Complete, and Verifiable code example 무엇이 잘못되었는지를 아는 것은 불가능합니다. 그러나 한 눈부신 오류 코드에 나타나지 않는 : 당신의 XAML에서

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

을, 당신은 {Binding Items}에 결합한다. DataContextItems 속성 값으로 설정된 경우 올바른 바인딩은 실제로는 {Binding}입니다.

XAML을 그대로 유지하려면 DataContext = this;을 대신 설정해야합니다. 물론 그렇게했다면 INotifyPropertyChanged.PropertyChanged을 발생시키지 않았거나 해당 인터페이스를 구현하는 것처럼 보이지 않는 문제에 부딪 힐 수 있습니다. InitializeComponent() 메서드가 호출되기 전에 프로퍼티가 설정 될 것이라고 확신하지만 표시되지 않은 코드에서는 문제가없는 것으로 생각하면 해결할 수 있습니다.

그래서 당신은 당신이 {Binding Items}에 바인딩을 설정하려는 경우도 INotifyPropertyChanged를 구현하고 당신은 당신이 실제로 속성을 설정 속성 이름 "Items"PropertyChanged 이벤트를 발생 있는지 확인해야합니다.

위의 질문에 대한 답변이 없으면 문제를 확실하게 재현 할 수있는 좋은 MCVE를 제공하여 문제를 개선하십시오.

+0

DataContext = Items을 변경 한 내가 DataContext를 변경 한 단지'당신이 제안'{바인딩}하지만 (내가 뭔가를 놓친 거지하지 않는 한)는 아무것도 변경하지 않았다. 나 또한 particulary 원하는 그냥 PropertyChanged 솔루션을 구현하는 방법을 그냥 또는 그것을 어떻게 작동하는지 모르겠다. 이 질문을 가능한 한 빨리 올바르게 정렬 할 수 있도록 노력할 것입니다. – Haybale100

+0

WPF 프로그램을 작성하려면 ** INotifyPropertyChanged에 대해 알아야하고이를 구현할 수 있어야합니다. 사소한 바인딩이 없으면 작동하지 않을 것입니다. 현재의 질문에 관한 한, 귀하의 질문에 게시 한 내용을 기반으로 한 조언 만 제공 할 수 있습니다. 'ItemsSource = "{Binding}"에 대한 바인딩을 변경해도 문제가 해결되지 않으면 게시 한 코드에 분명하지 않은 다른 문제가 있습니다. 좋은 [mcve]가 포함되도록 질문을 고정하면 확실한 답을 얻을 수 있습니다. –

관련 문제