【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
    }
LoopingDataSourceBase 抽象类

 

    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
        }
    }
ListLoopingDataSource

  注意,数据源如果是对象,必须实现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);
        }
    }
Person

 

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
    }
LoopSelectorPage.xaml.cs

好了,数据源的集合是用 IEnumerable<T>存放的,如果需要添加和删除该数据源,可以使用List<T>对象,或是ObservableCollection<T> 对象存储

posted @ 2014-03-22 11:37  bomo  阅读(527)  评论(0编辑  收藏  举报