【WP8】LoopingSelector
WP8的WindowsPhoneToolkit工具包中有一个 LoopingSelector
可以想选择日期或时间一样进行选择
1、首先当然是引用WindowsPhoneToolkit
在Nuget控制台:
PM> Install-Package WPtoolkit
2、LoopingSelector 的数据源是 ILoopingSelectorDataSource类型的,我们先实现两个类继承该接口
public abstract class LoopingDataSourceBase : ILoopingSelectorDataSource { #region ILoopingSelectorDataSource Members public abstract object GetNext(object relativeTo); public abstract object GetPrevious(object relativeTo); private object _selectedItem; public object SelectedItem { get { return _selectedItem; } set { if (!Equals(_selectedItem, value)) { object previousSelectedItem = _selectedItem; _selectedItem = value; OnSelectionChanged(previousSelectedItem, _selectedItem); } } } public event EventHandler<SelectionChangedEventArgs> SelectionChanged; protected virtual void OnSelectionChanged(object oldSelectedItem, object newSelectedItem) { var handler = SelectionChanged; if (handler != null) { handler(this, new SelectionChangedEventArgs(new[] {oldSelectedItem}, new[] {newSelectedItem})); } } #endregion }
public class ListLoopingDataSource<T> : LoopingDataSourceBase { private IComparer<T> comparer; private LinkedList<T> linkedList; private NodeComparer nodeComparer; private List<LinkedListNode<T>> sortedList; public IEnumerable<T> Items { get { return linkedList; } set { SetItemCollection(value); } } public IComparer<T> Comparer { get { return comparer; } set { comparer = value; } } private void SetItemCollection(IEnumerable<T> collection) { linkedList = new LinkedList<T>(collection); sortedList = new List<LinkedListNode<T>>(linkedList.Count); LinkedListNode<T> currentNode = linkedList.First; while (currentNode != null) { sortedList.Add(currentNode); currentNode = currentNode.Next; } IComparer<T> comparer = this.comparer; if (comparer == null) { if (typeof (IComparable<T>).IsAssignableFrom(typeof (T))) { comparer = Comparer<T>.Default; } else { throw new InvalidOperationException( "There is no default comparer for this type of item. You must set one."); } } nodeComparer = new NodeComparer(comparer); sortedList.Sort(nodeComparer); } public override object GetNext(object relativeTo) { int index = sortedList.BinarySearch(new LinkedListNode<T>((T) relativeTo), nodeComparer); if (index < 0) { return default(T); } LinkedListNode<T> node = sortedList[index].Next; if (node == null) { node = linkedList.First; } return node.Value; } public override object GetPrevious(object relativeTo) { int index = sortedList.BinarySearch(new LinkedListNode<T>((T) relativeTo), nodeComparer); if (index < 0) { return default(T); } LinkedListNode<T> node = sortedList[index].Previous; if (node == null) { node = linkedList.Last; } return node.Value; } private class NodeComparer : IComparer<LinkedListNode<T>> { private readonly IComparer<T> comparer; public NodeComparer(IComparer<T> comparer) { this.comparer = comparer; } #region IComparer<LinkedListNode<T>> Members public int Compare(LinkedListNode<T> x, LinkedListNode<T> y) { return comparer.Compare(x.Value, y.Value); } #endregion } }
注意,数据源如果是对象,必须实现IComparer<T>接口,否则会抛出异常,当然,也可以重写ListLoopingDataSource类
下面是数据源对象,我们这里定义为Person
public class Person : IComparable<Person> { public string Name { get; set; } public int Age { get; set; } public int CompareTo(Person other) { //比较两个对象:这里只比较名字 return String.CompareOrdinal(Name, other.Name); } }
3、接下来是数据绑定
<toolkitPrimitives:LoopingSelector x:Name="LoopingSelector" DataSource="{Binding Items}" ItemMargin="2,3,3,2" ItemSize="200,150" FontSize="33" > <toolkitPrimitives:LoopingSelector.ItemTemplate> <DataTemplate> <Grid> <StackPanel> <TextBlock Text="{Binding Name}"></TextBlock> <TextBlock Text="{Binding Age}"></TextBlock> </StackPanel> </Grid> </DataTemplate> </toolkitPrimitives:LoopingSelector.ItemTemplate> </toolkitPrimitives:LoopingSelector>
public partial class LoopSelectorPage : INotifyPropertyChanged { #region Items /// <summary> /// The <see cref="Items" /> property's name. /// </summary> public const string ItemsPropertyName = "Items"; private ListLoopingDataSource<Person> _items; /// <summary> /// 用于绑定到LoopingSelector的数据源对象 /// </summary> public ListLoopingDataSource<Person> Items { get { return _items; } set { if (_items == value) { return; } _items = value; RaisePropertyChanged(ItemsPropertyName); } } #endregion public LoopSelectorPage() { InitializeComponent(); LoadApplicationBar(); LoadData(); } private void LoadApplicationBar() { ApplicationBar = new ApplicationBar(); var appBarButton = new ApplicationBarIconButton(new Uri("/Assets/AppBar/appbar.add.rest.png", UriKind.Relative)) { Text = "test" }; appBarButton.Click += appBarButton_Click; ApplicationBar.Buttons.Add(appBarButton); } private void appBarButton_Click(object sender, EventArgs e) { //改变数据源 Items = new ListLoopingDataSource<Person> { Items = new ObservableCollection<Person> { new Person{Name = "Cnblogs", Age = 12}, new Person{Name = "CodePlex", Age = 12}, new Person{Name = "CodeProject", Age = 15}, new Person{Name = "CSDN", Age = 15}, new Person{Name = "51CTO", Age = 15}, }, }; //注意,如果改变了数据源,必须设置其SelectedItem属性 Items.SelectedItem = Items.Items.First(); } private void LoadData() { Items = new ListLoopingDataSource<Person> { Items = new ObservableCollection<Person> { new Person{Name = "aaa", Age = 12}, new Person{Name = "bbb", Age = 12}, new Person{Name = "ccc", Age = 15}, new Person{Name = "ddd", Age = 15}, new Person{Name = "eee", Age = 15}, }, }; //注意,如果改变了数据源,必须设置其SelectedItem属性 Items.SelectedItem = Items.Items.First(); //也可以监听选择改变的事件 Items.SelectionChanged += Items_SelectionChanged; } void Items_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e) { MessageBox.Show(string.Format("add:{0}", ((Person)e.AddedItems[0]).Name)); } #region INotifyPropertyChanged Members public event PropertyChangedEventHandler PropertyChanged; protected void RaisePropertyChanged(string name) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(name)); } } #endregion }
好了,数据源的集合是用 IEnumerable<T>存放的,如果需要添加和删除该数据源,可以使用List<T>对象,或是ObservableCollection<T> 对象存储