看见有人在微薄上讨论图片滚动的实现
水平有限搞不定,突然想起来SL ToolKits有个仿wp上日期、时间滚动的控件
定制下模版就比较形似图片滚动了
动手试试效果
首先找了120张WP壁纸,不过文件都比较小
然后新建工程,添加引用Microsoft.Phone.Controls.Toolkit.dll,添加图片,生成方式设为内容
参考Windows Phone Toolkit In Depth,使用LoopingSelector
首先创建类ListLoopingDataSource.cs
1
using
System;
2 using System . Windows . Controls;
3 using Microsoft . Phone . Controls . Primitives;
4 namespace LoopingSelectorpic
5 {
6 public abstract class LoopingDataSourceBase : ILoopingSelectorDataSource
7 {
8 private object selectedItem;
9
10 #region ILoopingSelectorDataSource Members
11
12 public abstract object GetNext ( object relativeTo ) ;
13
14 public abstract object GetPrevious ( object relativeTo ) ;
15
16 public object SelectedItem
17 {
18 get
19 {
20 return this . selectedItem;
21 }
22 set
23 {
24 // this will use the Equals method if it is overridden for the data source item class
25 if ( ! object . Equals ( this . selectedItem, value ) )
26 {
27 // save the previously selected item so that we can use it
28 // to construct the event arguments for the SelectionChanged event
29 object previousSelectedItem = this . selectedItem;
30 this . selectedItem = value ;
31 // fire the SelectionChanged event
32 this . OnSelectionChanged ( previousSelectedItem, this . selectedItem ) ;
33 }
34 }
35 }
36 public event EventHandler < SelectionChangedEventArgs > SelectionChanged;
37
38 protected virtual void OnSelectionChanged ( object oldSelectedItem, object newSelectedItem )
39 {
40 EventHandler < SelectionChangedEventArgs > handler =
41 this . SelectionChanged;
42 if ( handler ! = null )
43 {
44 handler ( this , new SelectionChangedEventArgs ( new object [ ] { oldSelectedItem } , new object [ ] { newSelectedItem } ) ) ;
45 }
46 }
47
48 #endregion
49 }
50 }
2 using System . Windows . Controls;
3 using Microsoft . Phone . Controls . Primitives;
4 namespace LoopingSelectorpic
5 {
6 public abstract class LoopingDataSourceBase : ILoopingSelectorDataSource
7 {
8 private object selectedItem;
9
10 #region ILoopingSelectorDataSource Members
11
12 public abstract object GetNext ( object relativeTo ) ;
13
14 public abstract object GetPrevious ( object relativeTo ) ;
15
16 public object SelectedItem
17 {
18 get
19 {
20 return this . selectedItem;
21 }
22 set
23 {
24 // this will use the Equals method if it is overridden for the data source item class
25 if ( ! object . Equals ( this . selectedItem, value ) )
26 {
27 // save the previously selected item so that we can use it
28 // to construct the event arguments for the SelectionChanged event
29 object previousSelectedItem = this . selectedItem;
30 this . selectedItem = value ;
31 // fire the SelectionChanged event
32 this . OnSelectionChanged ( previousSelectedItem, this . selectedItem ) ;
33 }
34 }
35 }
36 public event EventHandler < SelectionChangedEventArgs > SelectionChanged;
37
38 protected virtual void OnSelectionChanged ( object oldSelectedItem, object newSelectedItem )
39 {
40 EventHandler < SelectionChangedEventArgs > handler =
41 this . SelectionChanged;
42 if ( handler ! = null )
43 {
44 handler ( this , new SelectionChangedEventArgs ( new object [ ] { oldSelectedItem } , new object [ ] { newSelectedItem } ) ) ;
45 }
46 }
47
48 #endregion
49 }
50 }
然后创建类LoopingDataSourceBase.cs
1
using
System;
2 using System . Collections . Generic;
3 using System . Collections;
4 namespace LoopingSelectorpic
5 {
6 public class ListLoopingDataSource < T > : LoopingDataSourceBase
7 {
8 private LinkedList < T > linkedList;
9 private List < LinkedListNode < T > > sortedList;
10 private IComparer < T > comparer;
11 private NodeComparer nodeComparer;
12
13 public ListLoopingDataSource ( )
14 {
15 }
16
17 public IEnumerable < T > Items
18 {
19 get
20 {
21 return this . linkedList;
22 }
23 set
24 {
25 this . SetItemCollection ( value ) ;
26 }
27 }
28
29 private void SetItemCollection ( IEnumerable < T > collection )
30 {
31 this . linkedList = new LinkedList < T > ( collection ) ;
32
33 this . sortedList = new
34 List < LinkedListNode < T > > ( this . linkedList . Count ) ;
35 // initialize the linked list with items from the collections
36 LinkedListNode < T > currentNode = this . linkedList . First;
37 while ( currentNode ! = null )
38 {
39 this . sortedList . Add ( currentNode ) ;
40 currentNode = currentNode . Next;
41 }
42
43 IComparer < T > comparer = this . comparer;
44 if ( comparer = = null )
45 {
46 // if no comparer is set use the default one if available
47 if ( typeof ( IComparable < T > ) . IsAssignableFrom ( typeof ( T ) ) )
48 {
49 comparer = Comparer < T > . Default;
50 }
51 else
52 {
53 throw new InvalidOperationException ( " There is no default comparer for this type of item. You must set one. " ) ;
54 }
55 }
56
57 this . nodeComparer = new NodeComparer ( comparer ) ;
58 this . sortedList . Sort ( this . nodeComparer ) ;
59 }
60
61 public IComparer < T > Comparer
62 {
63 get
64 {
65 return this . comparer;
66 }
67 set
68 {
69 this . comparer = value ;
70 }
71 }
72
73 public override object GetNext ( object relativeTo )
74 {
75 // find the index of the node using binary search in the sorted list
76 int index = this . sortedList . BinarySearch ( new
77 LinkedListNode < T > ( ( T ) relativeTo ) , this . nodeComparer ) ;
78 if ( index < 0 )
79 {
80 return default ( T ) ;
81 }
82
83 // get the actual node from the linked list using the index
84 LinkedListNode < T > node = this . sortedList [ index ] . Next;
85 if ( node = = null )
86 {
87 // if there is no next node get the first one
88 node = this . linkedList . First;
89 }
90 return node . Value;
91 }
92
93 public override object GetPrevious ( object relativeTo )
94 {
95 int index = this . sortedList . BinarySearch ( new
96 LinkedListNode < T > ( ( T ) relativeTo ) , this . nodeComparer ) ;
97 if ( index < 0 )
98 {
99 return default ( T ) ;
100 }
101 LinkedListNode < T > node = this . sortedList [ index ] . Previous;
102 if ( node = = null )
103 {
104 // if there is no previous node get the last one
105 node = this . linkedList . Last;
106 }
107 return node . Value;
108 }
109
110 private class NodeComparer : IComparer < LinkedListNode < T > >
111 {
112 private IComparer < T > comparer;
113
114 public NodeComparer ( IComparer < T > comparer )
115 {
116 this . comparer = comparer;
117 }
118
119 #region IComparer < LinkedListNode < T > > Members
120
121 public int Compare ( LinkedListNode < T > x, LinkedListNode < T > y )
122 {
123 return this . comparer . Compare ( x . Value, y . Value ) ;
124 }
125
126 #endregion
127 }
128
129 }
130 }
2 using System . Collections . Generic;
3 using System . Collections;
4 namespace LoopingSelectorpic
5 {
6 public class ListLoopingDataSource < T > : LoopingDataSourceBase
7 {
8 private LinkedList < T > linkedList;
9 private List < LinkedListNode < T > > sortedList;
10 private IComparer < T > comparer;
11 private NodeComparer nodeComparer;
12
13 public ListLoopingDataSource ( )
14 {
15 }
16
17 public IEnumerable < T > Items
18 {
19 get
20 {
21 return this . linkedList;
22 }
23 set
24 {
25 this . SetItemCollection ( value ) ;
26 }
27 }
28
29 private void SetItemCollection ( IEnumerable < T > collection )
30 {
31 this . linkedList = new LinkedList < T > ( collection ) ;
32
33 this . sortedList = new
34 List < LinkedListNode < T > > ( this . linkedList . Count ) ;
35 // initialize the linked list with items from the collections
36 LinkedListNode < T > currentNode = this . linkedList . First;
37 while ( currentNode ! = null )
38 {
39 this . sortedList . Add ( currentNode ) ;
40 currentNode = currentNode . Next;
41 }
42
43 IComparer < T > comparer = this . comparer;
44 if ( comparer = = null )
45 {
46 // if no comparer is set use the default one if available
47 if ( typeof ( IComparable < T > ) . IsAssignableFrom ( typeof ( T ) ) )
48 {
49 comparer = Comparer < T > . Default;
50 }
51 else
52 {
53 throw new InvalidOperationException ( " There is no default comparer for this type of item. You must set one. " ) ;
54 }
55 }
56
57 this . nodeComparer = new NodeComparer ( comparer ) ;
58 this . sortedList . Sort ( this . nodeComparer ) ;
59 }
60
61 public IComparer < T > Comparer
62 {
63 get
64 {
65 return this . comparer;
66 }
67 set
68 {
69 this . comparer = value ;
70 }
71 }
72
73 public override object GetNext ( object relativeTo )
74 {
75 // find the index of the node using binary search in the sorted list
76 int index = this . sortedList . BinarySearch ( new
77 LinkedListNode < T > ( ( T ) relativeTo ) , this . nodeComparer ) ;
78 if ( index < 0 )
79 {
80 return default ( T ) ;
81 }
82
83 // get the actual node from the linked list using the index
84 LinkedListNode < T > node = this . sortedList [ index ] . Next;
85 if ( node = = null )
86 {
87 // if there is no next node get the first one
88 node = this . linkedList . First;
89 }
90 return node . Value;
91 }
92
93 public override object GetPrevious ( object relativeTo )
94 {
95 int index = this . sortedList . BinarySearch ( new
96 LinkedListNode < T > ( ( T ) relativeTo ) , this . nodeComparer ) ;
97 if ( index < 0 )
98 {
99 return default ( T ) ;
100 }
101 LinkedListNode < T > node = this . sortedList [ index ] . Previous;
102 if ( node = = null )
103 {
104 // if there is no previous node get the last one
105 node = this . linkedList . Last;
106 }
107 return node . Value;
108 }
109
110 private class NodeComparer : IComparer < LinkedListNode < T > >
111 {
112 private IComparer < T > comparer;
113
114 public NodeComparer ( IComparer < T > comparer )
115 {
116 this . comparer = comparer;
117 }
118
119 #region IComparer < LinkedListNode < T > > Members
120
121 public int Compare ( LinkedListNode < T > x, LinkedListNode < T > y )
122 {
123 return this . comparer . Compare ( x . Value, y . Value ) ;
124 }
125
126 #endregion
127 }
128
129 }
130 }
然后定义我们的数据类Picdata.cs
1
using
System;
2 using System . Net;
3 using System . Windows;
4 using System . Windows . Controls;
5 using System . Windows . Documents;
6 using System . Windows . Ink;
7 using System . Windows . Input;
8 using System . Windows . Media;
9 using System . Windows . Media . Animation;
10 using System . Windows . Shapes;
11
12 namespace LoopingSelectorpic
13 {
14 public class Picdata : IComparable < Picdata >
15 {
16 public string Name
17 {
18 get ;
19 set ;
20 }
21
22 public string Url
23 {
24 get ;
25 set ;
26 }
27 public int ID
28 {
29 get ;
30 set ;
31 }
32
33 #region IComparable < Picdata > Members
34
35 public int CompareTo ( Picdata other )
36 {
37 return this . ID . CompareTo ( other . ID ) ;
38 }
39
40 #endregion
41 }
42 }
2 using System . Net;
3 using System . Windows;
4 using System . Windows . Controls;
5 using System . Windows . Documents;
6 using System . Windows . Ink;
7 using System . Windows . Input;
8 using System . Windows . Media;
9 using System . Windows . Media . Animation;
10 using System . Windows . Shapes;
11
12 namespace LoopingSelectorpic
13 {
14 public class Picdata : IComparable < Picdata >
15 {
16 public string Name
17 {
18 get ;
19 set ;
20 }
21
22 public string Url
23 {
24 get ;
25 set ;
26 }
27 public int ID
28 {
29 get ;
30 set ;
31 }
32
33 #region IComparable < Picdata > Members
34
35 public int CompareTo ( Picdata other )
36 {
37 return this . ID . CompareTo ( other . ID ) ;
38 }
39
40 #endregion
41 }
42 }
然后在页面里添加LoopingSelector并定义模版(貌似工具箱里找不到,自己手打吧)
<
toolkit:LoopingSelector
x:Name
=
"
LoopingSelector1
"
ItemMargin
=
"
5
"
ItemSize
=
"
400,530
"
HorizontalAlignment
=
"
Center
"
VerticalAlignment
=
"
Center
"
Width
=
"
400
"
Height
=
"
696
"
>
< toolkit:LoopingSelector.ItemTemplate >
< DataTemplate >
< StackPanel >
< StackPanel Width = " 400 " Height = " 30 " >
< TextBlock Text = " {Binding Name} " HorizontalAlignment = " Center " VerticalAlignment = " Center " / >
< /StackPanel >
< Image Source = " {Binding Url} " Stretch = " Fill " Width = " 400 " Height = " 500 " / >
< TextBlock Text = " {Binding ID} " / >
< /StackPanel >
< /DataTemplate >
< /toolkit:LoopingSelector.ItemTemplate >
< /toolkit:LoopingSelector >
< toolkit:LoopingSelector.ItemTemplate >
< DataTemplate >
< StackPanel >
< StackPanel Width = " 400 " Height = " 30 " >
< TextBlock Text = " {Binding Name} " HorizontalAlignment = " Center " VerticalAlignment = " Center " / >
< /StackPanel >
< Image Source = " {Binding Url} " Stretch = " Fill " Width = " 400 " Height = " 500 " / >
< TextBlock Text = " {Binding ID} " / >
< /StackPanel >
< /DataTemplate >
< /toolkit:LoopingSelector.ItemTemplate >
< /toolkit:LoopingSelector >
最后在page_load里填充数据并绑定
private
void
PhoneApplicationPage_Loaded
(
object
sender,
RoutedEventArgs
e
)
{
List < Picdata > data = new List < Picdata > ( ) ;
for ( int i = 1 ; i < = 120 ; i + + )
{
data . Add ( new Picdata ( )
{
Name = i . ToString ( ) + " .jpg " ,
Url = new Uri ( " /pic/ " + i . ToString ( ) + " .jpg " ,UriKind . Relative ) . ToString ( ) ,
ID = i
} ) ;
}
this . LoopingSelector1 . DataSource = new ListLoopingDataSource < Picdata > ( )
{
Items = data,
SelectedItem = data [ 2 ]
} ;
}
{
List < Picdata > data = new List < Picdata > ( ) ;
for ( int i = 1 ; i < = 120 ; i + + )
{
data . Add ( new Picdata ( )
{
Name = i . ToString ( ) + " .jpg " ,
Url = new Uri ( " /pic/ " + i . ToString ( ) + " .jpg " ,UriKind . Relative ) . ToString ( ) ,
ID = i
} ) ;
}
this . LoopingSelector1 . DataSource = new ListLoopingDataSource < Picdata > ( )
{
Items = data,
SelectedItem = data [ 2 ]
} ;
}
看下效果:
后记:加载120张图片,模拟器还算流畅,不过真机滚动起来还是有明显的卡顿
估计图片少点的时候凑合能用吧,另外理论上旋转下可以横向滚动的,不过我旋转的貌似有点问题,总是位置不大合适,而且只有点击图片边缘部分才能滚动,望高手能指导下
源码:
本文转自 sun8134 博客园博客,原文链接:http://www.cnblogs.com/sun8134/archive/2012/04/26/2471688.html ,如需转载请自行联系原作者