三、编写视图页面
现在,让我们来看看如何编写两个示例网页。首先,第一个页面MainPage.xaml的构建非常简单,仅仅使用一个ListBox控件来显示组数据列表。
列表5: 主视图页面XAML关键标记代码
- <ListBox x:Name="MainListBox" Margin="0,0,-12,0" ItemsSource="{Binding Groups}"
- SelectionChanged="MainListBox_SelectionChanged">
- <ListBox.ItemTemplate>
- <DataTemplate>
- <StackPanel Margin="0,0,0,17" Width="432" Orientation="Horizontal">
- <TextBlock Text="{Binding GroupId}" TextWrapping="Wrap"
- Style="{StaticResource PhoneTextExtraLargeStyle}"/>
- <TextBlock Text="{Binding GroupName}" TextWrapping="Wrap" Margin="12,-
- 6,12,0" Style="{StaticResource PhoneTextSubtleStyle}"/>
- </StackPanel>
- </DataTemplate>
- </ListBox.ItemTemplate>
- </ListBox>
现在,稍有Siverlight经验的读者应当都会理解上面的标记代码。这里通过使用基本的数据绑定技术(我们使用ListBox)来渲染GroupViewModel实例的每一个属性值。
接下来,让我们看看主视图页面后台代码编写的情况。
列表6:主视图页面后台关键代码
- namespace WP7SterlingLearning
- {
- public partial class MainPage : PhoneApplicationPage
- {
- public MainPage()
- {
- InitializeComponent();
- DataContext = App.ViewModel;
- this.Loaded += new RoutedEventHandler(MainPage_Loaded);
- }
- private void MainListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
- {
- if (MainListBox.SelectedIndex == -1)
- return;
- NavigationService.Navigate(new Uri("/ContactList.xaml?selectedGroup=" + MainListBox.SelectedIndex, UriKind.Relative));
- MainListBox.SelectedIndex = -1;
- }
- private void MainPage_Loaded(object sender, RoutedEventArgs e)
- {
- if (!App.ViewModel.IsDataLoaded)
- {
- App.ViewModel.LoadData();
- }
- }
- }
- }
首先,在MainPage类的构造函数中,我们把DataContext属性绑定到App.ViewModel。这一点很重要,也展示了整个系统的用户描述层是如何实现的。
接下来,让我们来分析一下MainPage_Loaded方法-每次示例页面加载时都调用这个方法。预先检查一下是否有必要再次加载视图模型数据是一个很好的设计习惯。
最后一点值得注意的是ListBox控件的SelectionChanged事件处理程序。在这个方法中,我们首先判断用户是否点击了ListBox控件中的项目之一。如果没有选中某个项目,即可返回;否则,我们把当前用户导航到另一个网页ContactList.xaml,以显示对应于所选组对应的联系人信息。注意,在页面ContactList.xaml的OnNavigatedTo事件处理器中我们传递进参数selectedGroup。
至于页面ContactList.xaml,有点复杂,但仍然很容易理解。首先,让我们来看一下这个页面的XAML标记代码的情况。
列表7: 页面ContactList.xaml的XAML标记代码
- <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
- <ListBox x:Name="MainListBox" Margin="0,0,-12,0" >
- <ListBox.ItemTemplate>
- <DataTemplate>
- <StackPanel Margin="0,0,0,17" Width="432">
- <TextBlock Text="{Binding GroupId}" TextWrapping="Wrap"
- Style="{StaticResource PhoneTextExtraLargeStyle}"/>
- <TextBlock Text="{Binding Id}" TextWrapping="Wrap" Margin="12,-6,12,0"
- Style="{StaticResource PhoneTextSubtleStyle}"/>
- <TextBlock Text="{Binding Name}" TextWrapping="Wrap"
- Style="{StaticResource PhoneTextExtraLargeStyle}"/>
- <TextBlock Text="{Binding Email}" TextWrapping="Wrap" Margin="12,-
- 6,12,0" Style="{StaticResource PhoneTextSubtleStyle}"/>
- <Image Source="{Binding ThumbNail,Converter={StaticResource
- ImageConverter1}}" />
- </StackPanel>
- </DataTemplate>
- </ListBox.ItemTemplate>
- </ListBox>
- </Grid>
为了简单起见,我们还利用一个ListBox控件来展示联系人信息。同时,我们也使用了典型的Silverlight数据绑定技术。总体来看,上面代码中只有一点值得注意,即图像数据的显示问题。为此,代码中使用了一个自定义的类型转换器。
列表8: 自定义的类型转换器代码
- public class imageUrlConverter : IValueConverter
- {
- public object Convert(object value, Type targetType, object parameter,
- System.Globalization.CultureInfo culture)
- {
- if (value == null || parameter == null)
- {
- return value;
- }
- return new BitmapImage(new Uri((string)value, UriKind.RelativeOrAbsolute));
- }
- public object ConvertBack(object value, Type targetType, object parameter,
- System.Globalization.CultureInfo culture)
- {
- throw new NotImplementedException();
- }
- }
注意,在本示例实现方案中,在构建联系人Contact的实例时,我们只持有在ThumbNail属性中存储的联系人相关缩略图的路径信息。上面转换器的关键在于Convert方法。在这个方法中,我们通过图片路径返回对应于缩略图的BitmapImage实例。然后,我们将它设置为图像控件的Source属性。
至于页面ContactList.xaml后台代码的实现就很简单了,如下所示。
列表9: 页面ContactList.xaml后台代码的实现
- protected override void OnNavigatedTo(NavigationEventArgs e)
- {
- string selectedGroup = "";
- if (NavigationContext.QueryString.TryGetValue("selectedGroup", out selectedGroup))
- {
- int iGroup = int.Parse(selectedGroup);
- // Query from Database by key
- var contactList =from key in
- App.Database.Query().Where(
- x => x.LazyValue.Value.GroupId == iGroup + 1).ToList() select key.LazyValue.Value;
- MainListBox.ItemsSource=contactList;
- }
- }
OnNavigatedTo方法是Silverlight for WP7中的基本导航方法,不必再赘述了。在上面代码中,一旦我们接收下selectedGroup参数,我们即使用它来创建一个标准的Sterling查询语句。注意,要想全面领会这里的查询语句,你应该先知道LazyValue在Sterling使用中所起的重要作用。最后,我们把查询结果绑定到ListBox控件的ItemsSource属性。这就是全部!