LongListSelector 攻略

原文地址在这里http://www.geekchamp.com/articles/longlistselector-walkthrough

这篇文章覆盖了LongListSelector的基础用法。读完这篇文章后你会一个小型的代码库,半篇攻略大概会花费半个小时的时间,整篇攻略不会超过两个小时。顺便说一下你应该把每一步的代码都编译一下,来确保你跟得上步子没有跑题。

目录

基础

A.Installing the Silverlight toolkit

B.Creating a project

C.Adding a reference to the Silverlight toolkit

D.Adding a LongListSelector

E.Making a model

F.Connecting the model and the LongListSelector

G.Adding jumplist functionality

中级

H.Prettifying

I.Updating the LongListSelector at runtime

J.Doing something when the user taps an item

K.Touch feedback

L.Separating model and view

M.Leveraging the designer

N.Extra topic: Binding unrelated properties

高级

.Advanced topic: Recovering from a tombstone

新建一个工程:

在MainPage.xaml里面添加

<toolkit:LongListSelector Name="GroupedList"></toolkit:LongListSelector>

13.让我们来聊聊LongListSelector是如何显示数据的,把下面的代码加入我们上一步添加的LongListSelector的标签里面

<toolkit:LongListSelector.ItemTemplate>

     <DataTemplate>

        <TextBlock Text="{Binding Name}" />

    </DataTemplate>

</toolkit:LongListSelector.ItemTemplate>

14 我们也想看一下为分组而显示的文,把下面的代码放在ItemTemplate的下方

<toolkit:LongListSelector.GroupHeaderTemplate>

       <DataTemplate>

         <TextBlock Text="{Binding Name}" FontSize="32" Foreground="Green" />

       </DataTemplate>

 </toolkit:LongListSelector.GroupHeaderTemplate>

我们让分组文本以绿色显示,会和正文分开。

写一个数据模型(Model)

15 。在Solution Explorer的工程名上点击右键Add->New Folder 并组文件夹命名。给文件命名为Model

16. 在Model文件夹上点击右键Add->NewItems。新建一个类,并命名为:FoodItem

17.然后添加一个Name属性和一个构造函数

public string Name { get; private set; }

public FoodItem(string foodName)

{

   Name = foodName;

}

18.搞定了一个类,紧接着让我们在Model里面创建另一个类。就像我在第15步中添加FoodItem一样。给这个类命名为:FoodCategory

19 . Let's flesh out FoodCategory with a Name property, a List of FoodItems, a constructor, and a method to add items

让我们给个类加一个Name属性和一个List类型的FoodItems属性,一个构造函数,一个添加项的方法

public string Name { get; private set; }

public System.Collections.Generic.List<FoodItem> Items { get; private set; }

public FoodCategory(string categoryName)

{

         Name = categoryName;

         Items = new System.Collections.Generic.List<FoodItem>();

}

public void AddFoodItem(FoodItem foodItem)

{

   Items.Add(foodItem);

}

20.除此之外,因为FoodCategory是LongListSelector用于实现“分组”的类,所以需要实现IEnumerable接口。实现这个接口后,LongListSelector可以看见“组”内部的每个Item

public System.Collections.IEnumerator GetEnumerator()

{

   return this.Items.GetEnumerator();

}

把public class FoodCategory   替换成 public class FoodCategory : System.Collections.IEnumerable,并把下面的方法添加到FoodCategory中

建立Model和LongListSelector的联接.

 

21差不多要好了,在MainPage.xaml.cs里面添加下面的代码.当应用程序启动时代码会向LongListSelector里添加我们定义的数据

protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)

{

     base.OnNavigatedTo(e);

     if (GroupedList.ItemsSource == null)

      {

        System.Collections.Generic.List<Model.FoodCategory> foodCategories =new System.Collections.Generic.List<Model.FoodCategory>();

        /*---Make burger items---*/

      Model.FoodCategory burgers = new Model.FoodCategory("Burgers");

       burgers.AddFoodItem(new Model.FoodItem("Hamburger"));

      burgers.AddFoodItem(new Model.FoodItem("Chicken burger"));

      burgers.AddFoodItem(new Model.FoodItem("Turkey burger"));

     burgers.AddFoodItem(new Model.FoodItem("Black bean burger"));

    /*---Make fryer items---*/

   Model.FoodCategory fryer = new Model.FoodCategory("Fryer");

   fryer.AddFoodItem(new Model.FoodItem("Fries"));

   fryer.AddFoodItem(new Model.FoodItem("Onion rings"));

   fryer.AddFoodItem(new Model.FoodItem("Tater tots"));

   fryer.AddFoodItem(new Model.FoodItem("Mozzarella sticks"));

  /*---Make fish items---*/

   Model.FoodCategory fish = new Model.FoodCategory("Fish");

  fish.AddFoodItem(new Model.FoodItem("Salmon"));

  fish.AddFoodItem(new Model.FoodItem("Rainbow trout"));

  fish.AddFoodItem(new Model.FoodItem("Grilled tilapia"));

  foodCategories.Add(burgers);

  foodCategories.Add(fryer);

  foodCategories.Add(fish);

  GroupedList.ItemsSource = foodCategories;

}

}

22 编译运行看一下结果.

添加分组列表文本跳动功能.

23.我们已经创建了一个LongListSelector,但是当用户点击分组文本时却没有反应.(让我们修改它);回到MainPage.xaml中我们添加的ItemTemplate和GroupItemTemplate位置,添加一个 GroupItemTemplate

<toolkit:LongListSelector.GroupItemTemplate>

    <DataTemplate>

      <TextBlock Text="{Binding Name}" FontSize="32" Foreground="Green" />

   </DataTemplate>

</toolkit:LongListSelector.GroupItemTemplate>

24编译代码,运行.现在当你点击分组头时,你会看到会弹出一个列表.

修饰

到目前为止,你可能会想我没有美感,(我并不否认).让我们做点事,让他变得时髦点.

 

25. 把ItemTemplate内部改成这样:

<DataTemplate>
	<TextBlock Text="{Binding Name}" Padding="{StaticResource PhoneTouchTargetOverhang}" 
			FontSize="{StaticResource PhoneFontSizeMediumLarge}" />
</DataTemplate>
			

26. 把 GroupHeaderTemplate 的内部改成这样:

<DataTemplate>
	<Border Background="{StaticResource PhoneAccentBrush}" 
			Padding="{StaticResource PhoneTouchTargetOverhang}">
		<TextBlock Text="{Binding Name}" Style="{StaticResource PhoneTextGroupHeaderStyle}"/>
	</Border>
</DataTemplate>
			

27.把GroupItemTemplate 内部改成这样:

<DataTemplate>
	<Border Background="{StaticResource PhoneAccentBrush}" 
			Padding="{StaticResource PhoneTouchTargetOverhang}"
			Margin="{StaticResource PhoneTouchTargetOverhang}">
		<TextBlock Text="{Binding Name}" Style="{StaticResource PhoneTextGroupHeaderStyle}"/>
	</Border>
</DataTemplate>
29. 编译代码,并运行:   
LongListSelectorWalkthrough9[1] 

动态更新LongListSelector

The LongListSelector works (and now looks) fine with the data we add in when the app starts. But if we try to add something while the app is running, the changes don't show up in the LongListSelector :(

(If you don't care about this, skip this section; it makes things more confusing)

当程序运行时LongListSelector运行良好,但是在程序运行时,我们添加一些数据,却不能显示出来(如果你不在乎这点.跳过这段,它会使事情显得更困惑)

 

30. 首先我们先处理分组,在OnNavigationTo函数中,把foodCategories换成System.Collections.ObjectModel.ObservableCollection<Model.FoodCategory>.

现在,LongListSelector能看到foodCategories.我们无论添加哪一种食物,LongListSelector都会更新.

31. 现在我们处理Items,目前,FoodCateGory实现了IEnumerable接口.让FoodCategory继承OBservableCollection,当我们添加一种食物时,LongListSelector会自动通知改变

使用public class FoodCategory : System.Collections.IEnumerable  替换

public class FoodCategory : System.Collections.ObjectModel.ObservableCollection<FoodItem>  ,并且删除Items属性.还有在构造函数中设置Items的那行代码.保留AddFoodItem().

FoodCategory.cs 应该像这样:   
LongListSelectorWalkthrough10[1]

 

 

我们完成了数据绑定部分.让们添加一些数据.然而,LongList和StackPanel并不像,所以把LongListSelector的高硬编码为:535(更好的方法是把LongListSelector放在一个Grid里面).在LongListSelecotr上面添加第二个StackPanel,并把它的Orientation设置为Horzontal.添加一个TextBox到水平StackPanel中 并命名为:BurgerInput同时设置它的宽为270.
LongListSelectorWalkthrough11[1]

33.

我们需要让foodCategories对于按钮的click事件是可见的,所以把foodCategories的定义放到MainPage中使用为一个实例变量.
LongListSelectorWalkthrough12[1]

34.

下面准备添加button的Click事件.双击按钮生成事件处理函数.

if (BurgerInput.Text != "")
{
	foodCategories[0].Add(new Model.FoodItem(BurgerInput.Text));
	BurgerInput.Text = "";
}
			

我们使用ObservableCollection的Add方法来代替AddFoodItem.这样是因为ObservableCollection可以通知LongListSelector数据源发生了变化.

35.

编译运行你的代码.当你添加一个Steakburger时,应用会像下图.
LongListSelectorWalkthrough13[1]

Doing something when the user taps an item

用用户点击一个列表顶时做一些处理.

 

现在我们有了一个方便的LongListSelector了,但是除了可以添加元素外,我们不能和他进行别的什么交互.让我们处理一下.当用户点击一个数据项时,LongListSelector有所响应.

36.

立即为LongListSelector添加一个Tap事件.在xaml中的LongListSelecotor标签中输入Tap,按Tap键,visual Studio会自动创建Tab的事件处理函数.

 37.在Tap的事件处理函数中,加上下面代码

 

if (GroupedList.SelectedItem is Model.FoodItem)
{
	MessageBox.Show("You tapped on the food item " + ((Model.FoodItem)GroupedList.SelectedItem).Name);
}

 

This triggers a popup whenever the user taps on an item (but not when the user taps on one of the group categories).

当用户点击一个Item时会弹出一个MessageBox.(并不是用户点击每一个分组中的一项时)

38. 运行你的代码,并点列表中的一项.   
LongListSelectorWalkthrough14[1]

触摸反馈

如果你使用过"人脉"功能,你会注意到当你按下一个Item时,对应的Item会"移动".就好像那个Item会对你的触摸有反应一样.像这样的小东西让windows phone对用户来说显示非常吸引人.所以让我们在LongListSelector上面模拟这个功能.

39.

找到LongListSelector中的ItemTemplate模板,为TextBlock添加ManipulationStarted和ManipulationCompleted事件.当用户下压到一个控件上时会触发ManipulationStarted事件.当用户停止"下压"时会触发ManipulationCompleted事件.

MainPage.xaml要像下面这样.   
LongListSelectorWalkthrough15[1] 

40. 当下面这行代码添加到ManipulationStarted事件中.当用户点击Item时这行代码会把Item像下右移动两像素.  

((UIElement)sender).RenderTransform = new System.Windows.Media.TranslateTransform() { X = 2, Y = 2 };

41.然后把下面这行代码放到MainpulationCompleted中.当用户停止触摸时,把item理移动回初始位置.

((UIElement)sender).RenderTransform = null;
			

42. 运行程序. 
LongListSelectorWalkthrough16[1]   

分离模型和视图

在这个简单的LongListSelecotr中视图和数据模型都在MainPage中.现在让我们写一个控制器类来负责视图和模型的交互.

43.添加一个文件夹,并命名为:Controller.

44.在Controller中添加一个类并命名为:FoodController.cs

45.像FoodZController中添加下面这些代码,(为了趣味局长,这里使用了一个单例模式.)

 

private static FoodController foodController;

public static FoodController GetInstance()
{
	if (foodController == null)
	{
		foodController = new FoodController();
	}
	return foodController;
}
			

46.,像下面这样然后添加一个FoodCategories属性

public System.Collections.ObjectModel.ObservableCollection<Model.FoodCategory>
		FoodCategories { get; private set; }
			

47. 向FoodController添加这面的方法.保证用户仍可以添加burger

public void AddBurgerItem(string name)
{
	FoodCategories[0].Add(new Model.FoodItem(name));
}
			

48.

为FoolController创建一个构造函数,然后把数据初始化部分放到构造函数中.新的FoodController类应该像下面这样.
LongListSelectorWalkthrough17[1]   
LongListSelectorWalkthrough18[1]

49.

使用Controller.FoodController.GetInstance().AddBurgerItem(BurgerInput.Text) 替换MainPage中Button的事件函数中的代码.

用下面的代码替换OnNavigatedTo事件中的代码:

base.OnNavigatedTo(e);
if (this.DataContext == null)
{
	this.DataContext = Controller.FoodController.GetInstance();
}
			

 

现在可以把MainPage中的foodCategoried函数删除了.
LongListSelectorWalkthrough19[1]   
编译你的代码!

50. Now let's add the last link: in MainPage.xaml, find the LongListSelector tag, and add ItemsSource="{Binding FoodCategories}". This tells the LongListSelector to find its items in the FoodCategories property of its Binding - in this case, its Binding is inherited from the DataContext of MainPage, which we've set to be the FoodController instance. MainPage.xaml should look something like this:  

现在让我们添加最后的链接.找到:LongListSelector标签然后添加  ItemsSource="{Binding FoodCategories}".这告诉LongListSelector去它绑定的对象中的FoodCategories中找数据源.数据绑定是从MainPage中的DataContext继承而来.我们已经把DataContext设置成FoodController的实例.
LongListSelectorWalkthrough20[1]

51. 运行程序

利用设计器.

到目前为止,我们看到的MainPage左加的设计器并没有显示LongListSelector.让我们试着做点有用的事改变一下显示

52. Create a new folder (like before) and name it SampleData. Add a new XML file named SampleFoodData.xml. Go to SampleFoodData's properties (right-click onSampleFoodData -> Properties) and set its Build Action to Resource.

创建一个新文件夹并命名为:SampleData.然后添加一个xml文件,命名为:SampleFoodData.xml.找到xml的属性设置,将BuildAction设置为:Resource

53.在xml中添加下面的代码.本质上我们只是在xml中添加了一个FoodController

<controller:FoodController
    xmlns:controller="clr-namespace:LongListSelectorDemo.Controller">

</controller:FoodController>
			

 

(如果你没有给工程命名为:LongListSelectorDemo,那么使用现在的工程名替换它)

54.把这行添加到MainPage.xaml中

d:DataContext="{d:DesignData SampleData/SampleFoodData.xml}"   
这等同于 this.DataContext = Controller.FoodController.GetInstance();

55.编译你的代码你发现不用运行程序在设计器中就可以显示出longListSelector


LongListSelectorWalkthrough21[1]

额外提示:绑定不相关的属性

我想使用斜体字显示所有素食.我们把素食用boolean标识,但是我们如何才能把boolean类型转换成字体样式呢.对了我们用Converter

56.

马上为FoodItem添加一个IsVegetarian属性然后到FoodController类的构造函数中设置那些素食.  
LongListSelectorWalkthrough22[1] LongListSelectorWalkthrough23[1]

57让我们写一个Converter.向工程中添加一个文件夹,然后向文件夹中添加一个名为VegetarianFormattingConverter的类.

58. VegetarianFormattingConverter类需要实现IValueConverter接口.添加下面两个方法来实现这个接口.

public object Convert(object value, Type targetType, 
		object parameter, System.Globalization.CultureInfo culture)
{
	return null;
}

public object ConvertBack(object value, Type targetType, 
		object parameter, System.Globalization.CultureInfo culture)
{
	return null;
}
			

59. 使用下面的代码替换Converter()方法中的内容.

bool vegetarian = (bool)value;
if (vegetarian) return FontStyles.Italic;
else            return FontStyles.Normal;
			

这段代码的意思是我们想让素食都用斜体显示,其它的正常显示. 
LongListSelectorWalkthrough24[1]

60.

现在我们有了转换器类.我们需要把转换器类放到MainPage.xaml中的某个地方.

首先让我们添加一个转换器实例到MainPage.xaml的资源字典中去.先把这行放到toolkit声明行下面.

xmlns:converter="clr-namespace:LongListSelectorDemo.Converter"
			

 

添加下面这些内容

<phone:PhoneApplicationPage.Resources>
	<converter:VegetarianFormattingConverter x:Key="VegetarianConverter" />
</phone:PhoneApplicationPage.Resources>
			

61. 把到ItemTemplate然后把下面的代码放到TextBlock标签中:

FontStyle="{Binding IsVegetarian, Converter={StaticResource VegetarianConverter}}"
			

MainPage.xaml should look something like this:   
LongListSelectorWalkthrough25[1]

62. Build and run your code! If everything worked, the app should look like this:   
LongListSelectorWalkthrough26[1]   
(You may have noticed the designer already showed the changes before running the app.)

高级主题:从墓碑化还原数据.

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值