我正在尝试使用ObservableCollection构建LongListSelector(工具包)。我遵循了this教程,一切都与样本数据一致。 但是,一旦我尝试使用从Internet下载的数据填充列表,它就变得一团糟!有空组,项目放置不正确,很少有东西按字母顺序排序。
我正在使用此代码为所有字母创建空组:
private static readonly string Groups = "#abcdefghijklmnopqrstuvwxyz";
/* ... other things ... */
List<Country> empty = new List<Country>();
foreach (char c in Groups)
{
Group<Country> emptyGroup = new Group<Country>(c.ToString(), empty);
App.Colst.cityByCountryList.Add(emptyGroup);
}
然后我创建了一个WebClient,它从Internet下载xml文件并对其进行分析,以这种方式向组添加项目:
string id = dreader.GetAttribute("id");
string name = dreader.GetAttribute("name_it");
string citynumber = dreader.GetAttribute("citiesNumber");
if (id != null && id != "")
{
Group<Country> firstGroup = App.Colst.cityByCountryList[Groups.IndexOf(name.Substring(0, 1).ToLower())];
Country newCountry = new Country() { Lett = name.Substring(0, 1).ToLower(), Name = name };
firstGroup.Add(newCountry);
}
这是结果(我是新用户,我无法上传图片......所以我发布了链接):
如您所见,组“f”已正确创建,但“Francia”应位于“f”而不是“m”。此外,“f”应该在“g”之前:有时组正确排序(例如“奥地利”不是xml文件中的第一个,但它显示在列表的顶部,它应该在哪里!)和有时候不是(“Italia”是文件中列出的第一批国家之一,但在列表中它是在“u”之后!)...
有什么想法吗?
非常感谢。
答案 0 :(得分:1)
您是否尝试过使用不同的分组方法? silverlight工具包包含了一个很好的示例,展示了如何实现分组:
List movies = new List(); //Fill movie collection ... var moviesByCategory = from movie in movies group movie by movie.Category into c orderby c.Key select new PublicGrouping(c); linqMovies.ItemsSource = moviesByCategory;
PublicGrouping 的位置是:
/// /// A class used to expose the Key property on a dynamically-created Linq grouping. /// The grouping will be generated as an internal class, so the Key property will not /// otherwise be available to databind. /// /// The type of the key. /// The type of the items. public class PublicGrouping : IGrouping { private readonly IGrouping _internalGrouping; public PublicGrouping(IGrouping internalGrouping) { _internalGrouping = internalGrouping; } public override bool Equals(object obj) { PublicGrouping that = obj as PublicGrouping; return (that != null) && (this.Key.Equals(that.Key)); } public override int GetHashCode() { return Key.GetHashCode(); } #region IGrouping Members public TKey Key { get { return _internalGrouping.Key; } } #endregion #region IEnumerable Members public IEnumerator GetEnumerator() { return _internalGrouping.GetEnumerator(); } #endregion #region IEnumerable Members System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return _internalGrouping.GetEnumerator(); } #endregion }
答案 1 :(得分:0)
我确实喜欢这个:
ZoneDetails zones = new ZoneDetails();
AppUtility.CreateGroupedOC(zones);
/// <summary>
/// Groups a passed Contacts ObservableCollection
/// </summary>
/// <param name="InitialContactsList">Unordered collection of Contacts</param>
/// <returns>Grouped Observable Collection of Contacts suitable for the LongListSelector</returns>
public static ObservableCollection<GroupedOC<ZoneDetail>> CreateGroupedOC(ObservableCollection<ZoneDetail> InitialContactsList)
{
//Initialise the Grouped OC to populate and return
ObservableCollection<GroupedOC<ZoneDetail>> GroupedContacts = new ObservableCollection<GroupedOC<ZoneDetail>>();
//first sort our contacts collection into a temp List using LINQ
var SortedList = (from con in InitialContactsList
orderby con.Name
select con).ToList();
//Now enumerate throw the alphabet creating empty groups objects
//This ensure that the whole alphabet exists even if we never populate them
string Alpha = "#abcdefghijklmnopqrstuvwxyz";
foreach (char c in Alpha)
{
//Create GroupedOC for given letter
GroupedOC<ZoneDetail> thisGOC = new GroupedOC<ZoneDetail>(c.ToString());
//Create a temp list with the appropriate Contacts that have this NameKey
var SubsetOfCons = (from con in SortedList
where (string.Compare(con.Key, c.ToString(), StringComparison.OrdinalIgnoreCase) == 0)
select con).ToList<ZoneDetail>();
//Populate the GroupedOC
foreach (ZoneDetail csm in SubsetOfCons)
{
thisGOC.Add(csm);
}
//Add this GroupedOC to the observable collection that is being returned
// and the LongListSelector can be bound to.
GroupedContacts.Add(thisGOC);
}
return GroupedContacts;
}
public class GroupedOC<T> : ObservableCollection<T>
{
/// <summary>
/// The Group Title
/// </summary>
public string Title
{
get;
set;
}
/// <summary>
/// Constructor ensure that a Group Title is included
/// </summary>
/// <param name="name">string to be used as the Group Title</param>
public GroupedOC(string name)
{
this.Title = name;
}
/// <summary>
/// Returns true if the group has a count more than zero
/// </summary>
public bool HasItems
{
get {return (Count != 0);}
}
}