积极答复者
(WP8.1)关于Hub中添加ListView控件的数据绑定

问题
-
直接上代码:
<Hub Header="Hub" x:Name="hub"> <HubSection Header="HubSection 0"> <DataTemplate> <Grid x:Name="hubsection"> <ListView x:Name="lv"> <ListView.ItemTemplate> <DataTemplate> <TextBlock Text="{Binding StoryName}"/> </DataTemplate> </ListView.ItemTemplate> </ListView> </Grid> </DataTemplate> </HubSection> <HubSection Header="HubSection 1"> <DataTemplate> <Grid/> </DataTemplate> </HubSection> </Hub>
现在的问题是,在后台不能用this.lv.ItemsSource和this.hubsection.DataContext来绑定数据;
如何将数据绑定到ListView控件上?
2016年1月29日 10:07
答案
-
这个极有可能是你的代码逻辑为:进入该页面时加载数据,集合里的数据造成重复。
P.S:你的 lv.ItemSource 应该是一个 ObservableCollection<T> (通常来说绑定到 ListView 的都是这个类型)。假定你的 lv.ItemSource 是 ObservableCollection<MyData> _mySource;
解决方法:
方法①:在加载数据时,你的 _mySource 一般来说都要通过 _mySource.Add(data) 等操作添加数据,在所有向 _mySource 添加数据时都先判断数据是否已存在。为了方便,这里你可以写一些 ObservableCollection<T> 的扩展方法,比如我的项目中用的(仅供参考):
/// <summary> /// 提供 <see cref="ObservableCollection{T}"/> 扩展方法的类。 /// </summary> public static class ObservableCollectionExtension { /// <summary> /// 将整个 <see cref="ObservableCollection{T}"/> 添加到目标 <see cref="ObservableCollection{T}"/> 中。 /// </summary> /// <typeparam name="T">集合中的元素类型。</typeparam> /// <param name="source"><see cref="ObservableCollection{T}"/> 源。</param> /// <param name="target">目标 <see cref="ObservableCollection{T}"/>。</param> public static void AddTo<T>(this ObservableCollection<T> source, ObservableCollection<T> target) { foreach (var item in source) { if (item != null && !target.Contains(item)) { target.Add(item); } } } /// <summary> /// 将指定集合的元素插入到 <see cref="ObservableCollection{T}"/> 的指定索引处。 /// </summary> /// <typeparam name="T">集合中的元素类型。</typeparam> /// <param name="source"><see cref="ObservableCollection{T}"/> 源。</param> /// <param name="collection">应将其元素添加到 <see cref="ObservableCollection{T}"/> 的指定索引处的集合。</param> public static void InsertRange<T>(this ObservableCollection<T> source, int index, IEnumerable<T> collection) { foreach (var item in collection) { if (item != null && !source.Contains(item)) { source.Insert(index++, item); } } } /// <summary> /// 清除集合中的所有 <see cref="null"/> 对象。 /// </summary> /// <typeparam name="T">集合中的元素类型。</typeparam> /// <param name="source"><see cref="ObservableCollection{T}"/> 源。</param> public static void ClearNull<T>(this ObservableCollection<T> source) { int index = 0; foreach (var item in source) { if (item == null) { source.RemoveAt(index); } index++; } } }
当然,你也可以选择不这样做,直接每次添加完数据后再清理掉重复的数据:
_mySource.Distinct(); //这是.Net 自带的扩展方法,用于去除集合中重复的元素。
注意:注意:注意:如果你的数据是自定义的类(或者结构体),那么你一定一定要记得给这个类(结构体)重写 Equals(obj)、GetHashCode(),不然这个 Distinct() 方法不一定能真正去除重复的元素,因为它不知道怎么样去判断元素之间是不是一样的。
比如你的数据是一个 Person 类。成员有:String Name; String Id; uint Age;
public override bool Equals(object obj) { return this.Id == ((Person)obj).Id; } public override int GetHashCode() { return this.Id.GetHashCode(); } // 作为习惯,ToString 也重写了。 public override string ToString() { return this.Name; }
方法②:进入该页面时,在加载数据前先清空 _mySource。
- 已标记为答案 learn WP 2016年2月10日 9:39
2016年2月4日 14:16
全部回复
-
能通过前台实现绑定的我都不喜欢在后台绑定!!!x3
注意:<DataTemplate> 中的成员是无法在后台访问的,你可以在 <DataTemplate> 的上级绑定数据源,类似这样(注意,现在我已经不用 WP8/8.1 了,所以这样写失败了记得通知我!!!):
<Hub Header="Hub" x:Name="hub"> <HubSection Header="HubSection 0" DataContext="{Binding xxx}"> <DataTemplate> <Grid x:Name="hubsection"> <ListView x:Name="lv"> <ListView.ItemTemplate> <DataTemplate> <TextBlock Text="{Binding StoryName}"/> </DataTemplate> </ListView.ItemTemplate> </ListView> </Grid> </DataTemplate> </HubSection> <HubSection Header="HubSection 1"> <DataTemplate> <Grid/> </DataTemplate> </HubSection> </Hub>
- 已编辑 CodingNinja10 2016年1月30日 3:40
2016年1月30日 3:39 -
您好,
如果你给Hub指定了数据上下文,并在它的DataTemplate中放了一个ListView,那么在给ListView指定数据源时需要从它的数据上下文中获取,在代码中也就是DataContext,而你给Hub指定了DataContext,那么你就得绑定这个数据上下文中的属性值作为ListView的数据源,下面是我的代码,供你参考:
<Hub Header="Hub" x:Name="hub"> <HubSection Header="HubSection 0"> <DataTemplate> <Grid x:Name="hubsection"> <ListView x:Name="lv" ItemsSource="{Binding mysource}"> <ListView.ItemTemplate> <DataTemplate> <TextBlock Text="{Binding StoryName}"/> </DataTemplate> </ListView.ItemTemplate> </ListView> </Grid> </DataTemplate> </HubSection> <HubSection Header="HubSection 1"> <DataTemplate> <Grid/> </DataTemplate> </HubSection> </Hub>
public sealed partial class MainPage : Page { public ObservableCollection<Test> mysource { get; set; } public MainPage() { this.InitializeComponent(); mysource = new ObservableCollection<Test>(); mysource.Add(new Test() {StoryName="abc" }); mysource.Add(new Test() { StoryName = "def" }); hub.DataContext = this; } } public class Test { public string StoryName { get; set; } }
We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
Click HERE to participate the survey.- 已编辑 Xavier Xie-MSFT 2016年2月2日 6:04
- 已建议为答案 Xavier Xie-MSFT 2016年2月4日 9:53
2016年2月2日 6:03 -
这个极有可能是你的代码逻辑为:进入该页面时加载数据,集合里的数据造成重复。
P.S:你的 lv.ItemSource 应该是一个 ObservableCollection<T> (通常来说绑定到 ListView 的都是这个类型)。假定你的 lv.ItemSource 是 ObservableCollection<MyData> _mySource;
解决方法:
方法①:在加载数据时,你的 _mySource 一般来说都要通过 _mySource.Add(data) 等操作添加数据,在所有向 _mySource 添加数据时都先判断数据是否已存在。为了方便,这里你可以写一些 ObservableCollection<T> 的扩展方法,比如我的项目中用的(仅供参考):
/// <summary> /// 提供 <see cref="ObservableCollection{T}"/> 扩展方法的类。 /// </summary> public static class ObservableCollectionExtension { /// <summary> /// 将整个 <see cref="ObservableCollection{T}"/> 添加到目标 <see cref="ObservableCollection{T}"/> 中。 /// </summary> /// <typeparam name="T">集合中的元素类型。</typeparam> /// <param name="source"><see cref="ObservableCollection{T}"/> 源。</param> /// <param name="target">目标 <see cref="ObservableCollection{T}"/>。</param> public static void AddTo<T>(this ObservableCollection<T> source, ObservableCollection<T> target) { foreach (var item in source) { if (item != null && !target.Contains(item)) { target.Add(item); } } } /// <summary> /// 将指定集合的元素插入到 <see cref="ObservableCollection{T}"/> 的指定索引处。 /// </summary> /// <typeparam name="T">集合中的元素类型。</typeparam> /// <param name="source"><see cref="ObservableCollection{T}"/> 源。</param> /// <param name="collection">应将其元素添加到 <see cref="ObservableCollection{T}"/> 的指定索引处的集合。</param> public static void InsertRange<T>(this ObservableCollection<T> source, int index, IEnumerable<T> collection) { foreach (var item in collection) { if (item != null && !source.Contains(item)) { source.Insert(index++, item); } } } /// <summary> /// 清除集合中的所有 <see cref="null"/> 对象。 /// </summary> /// <typeparam name="T">集合中的元素类型。</typeparam> /// <param name="source"><see cref="ObservableCollection{T}"/> 源。</param> public static void ClearNull<T>(this ObservableCollection<T> source) { int index = 0; foreach (var item in source) { if (item == null) { source.RemoveAt(index); } index++; } } }
当然,你也可以选择不这样做,直接每次添加完数据后再清理掉重复的数据:
_mySource.Distinct(); //这是.Net 自带的扩展方法,用于去除集合中重复的元素。
注意:注意:注意:如果你的数据是自定义的类(或者结构体),那么你一定一定要记得给这个类(结构体)重写 Equals(obj)、GetHashCode(),不然这个 Distinct() 方法不一定能真正去除重复的元素,因为它不知道怎么样去判断元素之间是不是一样的。
比如你的数据是一个 Person 类。成员有:String Name; String Id; uint Age;
public override bool Equals(object obj) { return this.Id == ((Person)obj).Id; } public override int GetHashCode() { return this.Id.GetHashCode(); } // 作为习惯,ToString 也重写了。 public override string ToString() { return this.Name; }
方法②:进入该页面时,在加载数据前先清空 _mySource。
- 已标记为答案 learn WP 2016年2月10日 9:39
2016年2月4日 14:16