LongListSelector不显示项目

时间:2013-04-01 20:55:54

标签: c# silverlight windows-phone-7 silverlight-toolkit 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();
    }
}

如果我显示任务列表框,那么一切都显示良好。但是,如果我显示分组的项目,则不会显示任何项目。

应用程序仅运行wel(无崩溃),只丢失LongListSelector中的项目。

我做错了什么?

1 个答案:

答案 0 :(得分: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; }
    }
}