摘要:用LongListSelector代替ListBox
若想要呈現一大筆資料的時候,想必大家應該是用ListBox來輸出吧,如果是想要做到拉到最底或是最頂端更新的話,要修改一些東西才能達到效果,若還要移動到指定的項目的話,這又要寫一堆有的沒的,拋棄它吧,來用更好用的LongListSelector!
這個控件是SilverLightToolkit裡的一員,不過Windows Phone 8也內建此控件了,且是像聯絡人那樣子的,連動畫都幫你做好了!這可真是德政啊!不過我現在要介紹的是在Windows Phone 7.5裡用的,8的以後再介紹,其實沒差很多就是。
不過有些準備工作是要先完成的,首先要先下載SilverLight Toolkit的原始碼回來編譯,因為雖然LongListSelector裡面有留StrechingTop,StrechingBottom,以及StrechingCompleted,但是拿來使用的時候卻一點反應都沒有,看了一下原始碼,原來雖然有放,但是卻沒有去實作就是,所以這邊就要我們自己去處理了。
先打開SilverLight Toolkit的專案,然後再打開LongListSelector/LongListSelector.cs,首先先找到public override void OnApplyTemplate(),下面這段
FrameworkElement element = VisualTreeHelper.GetChild(sv, 0) as FrameworkElement;
if (element != null)
{
_scrollGroup = VisualStates.TryGetVisualStateGroup(sv, ScrollStatesGroupName);
if (_scrollGroup != null)
{
_scrollGroup.CurrentStateChanging += OnScrollStateChanging;
}
_verticalCompressionGroup = VisualStates.TryGetVisualStateGroup(sv, VerticalCompressionStateName);
if (_verticalCompressionGroup != null)
{
_verticalCompressionGroup.CurrentStateChanging += OnStretchStateChanging;
}
}
改成
FrameworkElement element = VisualTreeHelper.GetChild(sv, 0) as FrameworkElement;
if (element != null)
{
_scrollGroup = VisualStates.TryGetVisualStateGroup(sv, "ScrollStates");
if (_scrollGroup != null)
{
_scrollGroup.CurrentStateChanging += OnScrollStateChanging;
}
var verticalGroup = VisualStates.TryGetVisualStateGroup(sv, "VerticalCompression");
if (verticalGroup != null)
{
verticalGroup.CurrentStateChanging += OnScrollStateChanging;
}
}
然後再找到private void OnScrollStateChanging(object sender, VisualStateChangedEventArgs e)內容改成
IsScrolling = e.NewState.Name == ScrollingState;
if (e.NewState.Name == ScrollingState && ScrollingStarted != null)
{
ScrollingStarted(this, null);
}
else if (e.NewState.Name == NotScrollingState && ScrollingCompleted != null)
{
ScrollingCompleted(this, null);
}
else if (e.NewState.Name == CompressionTop && StretchingTop != null)
{
StretchingTop(this, null);
}
else if (e.NewState.Name == CompressionBottom && StretchingBottom != null)
{
StretchingBottom(this, null);
}
else if (e.NewState.Name == NoVerticalCompression && StretchingCompleted != null)
{
StretchingCompleted(this, null);
}
改完再編譯,這樣準備工作就完成啦,接下來就可以用到你自己的專案了,這裡先做個簡單範例,首先當然是先引用你剛剛完成的Microsoft.Phone.Controls.Toolkit.dll,然後在xaml檔裡放入
<toolkit:LongListSelector x:Name="testLongListSelector" IsFlatList="True" Margin="0,0,0,106">
<toolkit:LongListSelector.ItemTemplate>
<DataTemplate>
<StackPanel Background="Red" Margin="10">
<TextBlock Text="{Binding Name}" FontSize="28" HorizontalAlignment="Left" />
<TextBlock Text="{Binding Phone}" FontSize="28" HorizontalAlignment="Left" />
</StackPanel>
</DataTemplate>
</toolkit:LongListSelector.ItemTemplate>
</toolkit:LongListSelector>
IsFlatList記得設成True,這樣行為才會像一般的ListBox,接下來要設定Resource,在空白處加入這段
<phone:PhoneApplicationPage.Resources>
<Style TargetType="ScrollViewer">
<Setter Property="VerticalScrollBarVisibility" Value="Auto"/>
<Setter Property="HorizontalScrollBarVisibility" Value="Auto"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ScrollViewer">
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="ScrollStates">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="00:00:00.5"/>
</VisualStateGroup.Transitions>
<VisualState x:Name="Scrolling">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="VerticalScrollBar"
Storyboard.TargetProperty="Opacity" To="1" Duration="0"/>
<DoubleAnimation Storyboard.TargetName="HorizontalScrollBar"
Storyboard.TargetProperty="Opacity" To="1" Duration="0"/>
</Storyboard>
</VisualState>
<VisualState x:Name="NotScrolling">
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="VerticalCompression">
<VisualState x:Name="NoVerticalCompression"/>
<VisualState x:Name="CompressionTop"/>
<VisualState x:Name="CompressionBottom"/>
<VisualState x:Name="StretchingTop"/>
<VisualState x:Name="StretchingBottom"/>
</VisualStateGroup>
<VisualStateGroup x:Name="HorizontalCompression">
<VisualState x:Name="NoHorizontalCompression"/>
<VisualState x:Name="CompressionLeft"/>
<VisualState x:Name="CompressionRight"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid Margin="{TemplateBinding Padding}">
<ScrollContentPresenter x:Name="ScrollContentPresenter" Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"/>
<ScrollBar x:Name="VerticalScrollBar" IsHitTestVisible="False" Height="Auto" Width="5"
HorizontalAlignment="Right" VerticalAlignment="Stretch" Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}"
IsTabStop="False" Maximum="{TemplateBinding ScrollableHeight}" Minimum="0" Value="{TemplateBinding VerticalOffset}"
Orientation="Vertical" ViewportSize="{TemplateBinding ViewportHeight}" />
<ScrollBar x:Name="HorizontalScrollBar" IsHitTestVisible="False" Width="Auto" Height="5"
HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}"
IsTabStop="False" Maximum="{TemplateBinding ScrollableWidth}" Minimum="0" Value="{TemplateBinding HorizontalOffset}"
Orientation="Horizontal" ViewportSize="{TemplateBinding ViewportWidth}" />
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</phone:PhoneApplicationPage.Resources>
這邊主要是設定ScrollView的Style,接下來到程式碼裡面,加入
public class CTest
{
public string Name { get; set; }
public string Phone { get; set; }
}
private void test()
{
List listTest = new List();
listTest.Add(new CTest { Name = "01", Phone = "12345" });
listTest.Add(new CTest { Name = "02", Phone = "12345" });
listTest.Add(new CTest { Name = "03", Phone = "12345" });
listTest.Add(new CTest { Name = "04", Phone = "12345" });
listTest.Add(new CTest { Name = "05", Phone = "12345" });
listTest.Add(new CTest { Name = "06", Phone = "12345" });
listTest.Add(new CTest { Name = "07", Phone = "12345" });
listTest.Add(new CTest { Name = "08", Phone = "12345" });
listTest.Add(new CTest { Name = "09", Phone = "12345" });
this.testLongListSelector.ItemsSource = listTest;
}
然後在頁面建構式裡面跑test(),就會看到畫面了,看起來是不是跟一般的ListBox一樣呢!然後如果我們要加上拉到最底更新或拉到最上更新,就可以利用這三個事件來達成目的
this.testLongListSelector.StretchingBottom += new EventHandler(testLong_StretchingBottom);
void testLong_StretchingBottom(object sender, EventArgs e)
{
MessageBox.Show("Bottom");
}
this.testLongListSelector.StretchingCompleted += new EventHandler(testLong_StretchingCompleted);
void testLong_StretchingCompleted(object sender, EventArgs e)
{
MessageBox.Show("Finished");
}
this.testLongListSelector.StretchingTop += new EventHandler(testLong_StretchingTop);
void testLong_StretchingTop(object sender, EventArgs e)
{
MessageBox.Show("Top");
}
例如拉到最上更新的話,我們可以在使用者拉到最上的時候,也就是會跑StretchingTop這邊放個判斷說使用者拉到最上,然後當使用者放開的時候,也就是會跑StretchingCompleted這邊來計時說拉到最上幾秒才要更新,這樣就可以達到需求了。如果你還想要讓畫面滑到你想指定的項目的話,可以使用ScrollTo(object item)來達成喔。
大概就是這個樣子,之後再寫一篇有關Windows Phone 8的LongListSelector的介紹吧!