我实现了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中的项目。
我做错了什么?
答案 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; }
}
}