0

我實現LongListSelector,因爲我想分組項目。但是,當我運行它時,這個LongListSelector不顯示任何項目。LongListSelector不顯示項目

這是我的XML數據源:

<?xml version="1.0" encoding="utf-8"?> 
<Tasks> 
    <Task> 
    <Name>first task</Name> 
    <DueDate>05/03/2013 00:00:00</DueDate> 
    <Created>03/27/2013 01:24:08</Created> 
    </Task> 
    <Task> 
    <Name>second task</Name> 
    <DueDate>05/17/2013 00:00:00</DueDate> 
    <Created>03/27/2013 01:24:19</Created> 
    </Task> 
    <Task> 
    <Name>third task</Name> 
    <DueDate>05/17/2013 00:00:00</DueDate> 
    <Created>03/27/2013 01:24:38</Created> 
    </Task> 
</Tasks> 

我的XAML代碼:

<toolkit:LongListSelector Background="Transparent" ItemsSource="{Binding TasksByDueDate}"> 
    <toolkit:LongListSelector.GroupHeaderTemplate> 
     <DataTemplate> 
      <Border Background="Transparent"> 
       <Border Background="{StaticResource PhoneAccentBrush}" Width="475" Height="35" HorizontalAlignment="Left"> 
        <TextBlock Text="{Binding Key}" 
          Foreground="{StaticResource PhoneForegroundBrush}" 
          Style="{StaticResource PhoneTextGroupHeaderStyle}" 
          VerticalAlignment="Bottom"/> 
       </Border> 
      </Border> 
     </DataTemplate> 
    </toolkit:LongListSelector.GroupHeaderTemplate> 
    <toolkit:LongListSelector.ItemTemplate> 
     <DataTemplate> 
      <StackPanel Margin="0,0,0,17" Width="432" Orientation="Horizontal"> 
       <TextBlock Text="{Binding Name}" TextWrapping="Wrap" Width="345"/> 
      </StackPanel> 
     </DataTemplate> 
    </toolkit:LongListSelector.ItemTemplate> 
</toolkit:LongListSelector> 

MainViewModel.cs:

public class MainViewModel : INotifyPropertyChanged 
{ 
    public ObservableCollection<Task> Tasks { get; private set; } 

    public IEnumerable<Group<string, Task>> TasksByDueDate { get; private set; } 

    public MainViewModel() 
    { 
     this.Tasks = new ObservableCollection<Task>(); 
     this.Projects = new ObservableCollection<Project>(); 
     this.Contexts = new ObservableCollection<Context>(); 
    } 

    public bool IsDataLoaded { get; private set; } 

    public void LoadPlannedData() 
    { 
     try 
     { 
      Tasks.Clear(); 

      var file = IsolatedStorageFile.GetUserStoreForApplication(); 
      XElement xElem; 

      using (IsolatedStorageFileStream read = file.OpenFile("tasks.xml", FileMode.Open)) 
      { 
       xElem = XElement.Load(read); 
      } 

      var tasks = from task in xElem.Elements("Task") 
         orderby (DateTime)task.Element("Created") descending 
         select task; 

      foreach (XElement xElemItem in tasks) 
      { 
       Tasks.Add(new Task 
       { 
        Name = xElemItem.Element("Name").Value.ToString(), 
        DueDate = xElemItem.Element("DueDate").Value.ToString(), 
        Created = xElemItem.Element("Created").Value.ToString() 
       }); 
      } 

      TasksByDueDate = from c in Tasks 
          group c by c.DueDate into n 
          select new Group<string, Task>(n); 
     } 
     catch (Exception ex) 
     { 
      MessageBox.Show(ex.Message); 
     } 

     this.IsDataLoaded = true; 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 
    private void NotifyPropertyChanged(String propertyName) 
    { 
     PropertyChangedEventHandler handler = PropertyChanged; 
     if (null != handler) 
     { 
      handler(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 
} 

Group.cs:

public class Group<TKey, TElement> : IGrouping<TKey, TElement> 
{ 
    private readonly IGrouping<TKey, TElement> grouping; 

    public Group(IGrouping<TKey, TElement> unit) 
    { 
     grouping = unit; 
    } 

    public TKey Key 
    { 
     get { return grouping.Key; } 
    } 

    public IEnumerator<TElement> GetEnumerator() 
    { 
     return grouping.GetEnumerator(); 
    } 

    IEnumerator IEnumerable.GetEnumerator() 
    { 
     return grouping.GetEnumerator(); 
    } 
} 

如果我顯示任務列表框,那麼一切都顯示良好。但是,如果我顯示分組項目,則不會顯示任何項目。

應用程序運行良好(沒有崩潰)只有LongListSelector中的項缺失。

我在做什麼錯?

回答

1

我花了2-3天的時間追查同樣的問題,這是一場噩夢。我相信答案是ItemsSource數據格式需要是IList。不幸的是,這並不會對你有很大的幫助,但是這裏有兩個我創建的類......至少他們至少工作。

我的StringKeyGroup允許使用全文組名,而AlphaKeyGroup使列表字母順序排列。

StringKeyGroup類

using System.Collections.Generic; 
using System.Collections.ObjectModel; 
using System.Globalization; 
using System.Linq; 

namespace LongListSelectorDemo.Model 
{ 
    public class StringKeyGroup<T> : ObservableCollection<T> 
    { 
     public delegate string GetKeyDelegate(T item); 
     public string Key { get; private set; } 
     public StringKeyGroup(string key) 
     { 
      Key = key; 
     } 
     public static ObservableCollection<StringKeyGroup<T>> CreateGroups(IEnumerable<T> items, CultureInfo ci, GetKeyDelegate getKey, bool sort) 
     { 
      var list = new ObservableCollection<StringKeyGroup<T>>(); 

      foreach (var item in items) 
      { 
       var index = -1; 
       for (var i = 0; i < list.Count; i++) 
       { 
        if (list[i].Key.Equals(getKey(item))) 
        { 
         index = i; 
         break; 
        } 
       } 
       if (index == -1) 
       { 
        list.Add(new StringKeyGroup<T>(getKey(item))); 
        index = list.Count - 1; 
       } 
       if (index >= 0 && index < list.Count) 
       { 
        list[index].Add(item); 
       } 
      } 

      if (sort) 
      { 
       foreach (var group in list) 
       { 
        group.ToList().Sort((c0, c1) => ci.CompareInfo.Compare(getKey(c0), getKey(c1))); 
       } 
      } 

      return list; 
     } 
    } 
} 

AlphaKeyGroup類

using System.Collections.Generic; 
using System.Collections.ObjectModel; 
using System.Globalization; 
using System.Linq; 
using Microsoft.Phone.Globalization; 

namespace LongListSelectorDemo.Model 
{ 
    public class AlphaKeyGroup<T> : ObservableCollection<T> 
    { 
     /// <summary> 
     /// The delegate that is used to get the key information. 
     /// </summary> 
     /// <param name="item">An object of type T</param> 
     /// <returns>The key value to use for this object</returns> 
     public delegate string GetKeyDelegate(T item); 

     /// <summary> 
     /// The Key of this group. 
     /// </summary> 
     public string Key { get; private set; } 

     /// <summary> 
     /// Public constructor. 
     /// </summary> 
     /// <param name="key">The key for this group.</param> 
     public AlphaKeyGroup(string key) 
     { 
      Key = key; 
     } 

     /// <summary> 
     /// Create a list of AlphaGroup<T> with keys set by a SortedLocaleGrouping. 
     /// </summary> 
     /// <param name="slg">The </param> 
     /// <returns>Theitems source for a LongListSelector</returns> 
     private static ObservableCollection<AlphaKeyGroup<T>> CreateGroups(SortedLocaleGrouping slg) 
     { 
      return new ObservableCollection<AlphaKeyGroup<T>>(slg.GroupDisplayNames.Select(key => new AlphaKeyGroup<T>(key)).ToList()); 
     } 

     /// <summary> 
     /// Create a list of AlphaGroup<T> with keys set by a SortedLocaleGrouping. 
     /// </summary> 
     /// <param name="items">The items to place in the groups.</param> 
     /// <param name="ci">The CultureInfo to group and sort by.</param> 
     /// <param name="getKey">A delegate to get the key from an item.</param> 
     /// <param name="sort">Will sort the data if true.</param> 
     /// <returns>An items source for a LongListSelector</returns> 
     public static ObservableCollection<AlphaKeyGroup<T>> CreateGroups(IEnumerable<T> items, CultureInfo ci, GetKeyDelegate getKey, bool sort) 
     { 
      var slg = new SortedLocaleGrouping(ci); 
      var list = CreateGroups(slg); 

      foreach (var item in items) 
      { 
       var index = 0; 
       if (slg.SupportsPhonetics) 
       { 
        //check if your database has yomi string for item 
        //if it does not, then do you want to generate Yomi or ask the user for this item. 
        //index = slg.GetGroupIndex(getKey(Yomiof(item))); 
       } 
       else 
       { 
        index = slg.GetGroupIndex(getKey(item)); 
       } 
       if (index >= 0 && index < list.Count) 
       { 
        list[index].Add(item); 
       } 
      } 

      if (sort) 
      { 
       foreach (var group in list) 
       { 
        group.ToList().Sort((c0, c1) => ci.CompareInfo.Compare(getKey(c0), getKey(c1))); 
       } 
      } 

      return list; 
     } 
    } 
} 

實施例的使用,只是交換StringKeyGroup和AlphaKeyGroup之間的類名看出差別:

XAML

<phone:PhoneApplicationPage 
    x:Class="LongListSelectorDemo.MainPage" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone" 
    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    mc:Ignorable="d" 
    FontFamily="{StaticResource PhoneFontFamilyNormal}" 
    FontSize="{StaticResource PhoneFontSizeNormal}" 
    Foreground="{StaticResource PhoneForegroundBrush}" 
    SupportedOrientations="Portrait" Orientation="Portrait" 
    shell:SystemTray.IsVisible="True"> 

    <!--LayoutRoot is the root grid where all page content is placed--> 
    <Grid x:Name="LayoutRoot" Background="Transparent"> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="Auto"/> 
      <RowDefinition Height="*"/> 
     </Grid.RowDefinitions> 

     <!--TitlePanel contains the name of the application and page title--> 
     <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28"> 
      <TextBlock Text="MY APPLICATION" Style="{StaticResource PhoneTextNormalStyle}" Margin="12,0"/> 
      <TextBlock Text="page name" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/> 
     </StackPanel> 

     <!--ContentPanel - place additional content here--> 
     <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> 
      <phone:LongListSelector x:Name="GroupedList" IsGroupingEnabled="True" HideEmptyGroups="True"> 
       <phone:LongListSelector.ItemTemplate> 
        <DataTemplate> 
         <TextBlock Text="{Binding Name}" Padding="{StaticResource PhoneTouchTargetOverhang}" 
      FontSize="{StaticResource PhoneFontSizeMediumLarge}" /> 
        </DataTemplate> 
       </phone:LongListSelector.ItemTemplate> 
       <phone:LongListSelector.GroupHeaderTemplate> 
        <DataTemplate> 
         <Border Background="{StaticResource PhoneAccentBrush}" 
      Padding="{StaticResource PhoneTouchTargetOverhang}"> 
          <TextBlock Text="{Binding Key}" Style="{StaticResource PhoneTextGroupHeaderStyle}"/> 
         </Border> 
        </DataTemplate> 
       </phone:LongListSelector.GroupHeaderTemplate> 
      </phone:LongListSelector> 
     </Grid> 
    </Grid> 

</phone:PhoneApplicationPage> 

XAML.cs

using System.Collections.Generic; 
using System.Collections.ObjectModel; 
using LongListSelectorDemo.Model; 
using Microsoft.Phone.Controls; 

namespace LongListSelectorDemo 
{ 
    public partial class MainPage : PhoneApplicationPage 
    { 
     // Constructor 
     public MainPage() 
     { 
      InitializeComponent(); 

      // Sample code to localize the ApplicationBar 
      //BuildLocalizedApplicationBar(); 
     } 

     protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e) 
     { 
      base.OnNavigatedTo(e); 
      if (GroupedList.ItemsSource == null) 
      { 
       var foodItems = new ObservableCollection<FoodItem>(); 

       /*---Make burger items---*/ 
       foodItems.Add(new FoodItem("Hamburger", "Burgers")); 
       foodItems.Add(new FoodItem("Chicken burger", "Burgers")); 
       foodItems.Add(new FoodItem("Turkey burger", "Burgers")); 
       foodItems.Add(new FoodItem("Black bean burger", "Burgers")); 

       /*---Make fryer items---*/ 
       foodItems.Add(new FoodItem("Fries", "Fryer")); 
       foodItems.Add(new FoodItem("Onion rings", "Fryer")); 
       foodItems.Add(new FoodItem("Tater tots", "Fryer")); 
       foodItems.Add(new FoodItem("Mozzarella sticks", "Fryer")); 

       /*---Make fish items---*/ 
       foodItems.Add(new FoodItem("Salmon", "Fish")); 
       foodItems.Add(new FoodItem("Rainbow trout", "Fish")); 
       foodItems.Add(new FoodItem("Grilled tilapia", "Fish")); 

       GroupedList.ItemsSource = GroupedItems(foodItems); 
      } 
     } 

     public ObservableCollection<StringKeyGroup<FoodItem>> GroupedItems(IEnumerable<FoodItem> source) 
     { 
      return StringKeyGroup<FoodItem>.CreateGroups(source, 
    System.Threading.Thread.CurrentThread.CurrentUICulture, s => s.GroupName, true); 
     } 
    } 
} 

這裏是FoodItem類:

namespace LongListSelectorDemo.Model 
{ 
    public class FoodItem 
    { 
     public FoodItem(string name, string groupName) 
     { 
      Name = name; 
      GroupName = groupName; 
     } 
     public string Name { get; private set; } 
     public string GroupName { get; private set; } 
    } 
}