Silverlight实例秀——可切换视图的DataTemplate(做网站必备技术)

 Silverlight实例秀——可切换视图的DataTemplate(做网站必备技术)

 

小序:

敏捷开发也是要有个度的。搞敏捷,最起码的限度是程序员要对手里使用的工具比较精通。

相信大家都见过这个场景:

问:“你在做什么?”
程序员:“我在敏捷开发。”
问:“这样设计不对吧……”
程序员:“没事儿,我可以重构!”

拜托,手里使用的工具都不了解,程序中到处都是诡异的方法……怎么重构?天生就是一恐龙,再怎么重构也变不成人呀!这时候,唯一能做的就是——重写。

 

正文:

 

今天的例子就是一个由错误程序重写而来的结果。至于那个错误程序,下周我将另写一文《WPF的典型误用》。

客户的需求是这样的:要求用Silverlight写一个留言板,打开界面后,可以看到一个留言列表,每条留言只显示标题、发言人和发言时间。每条留言有一个切换按钮,可以显示和隐藏留言的详细信息。

 

实现这个功能很简单。用一个ListBox加上一个DataTemplate就搞定了。这里着重提示一句:DataTemplate就是“数据的外衣”,只有理解了DataTemplate才能明白WPF的精髓——数据驱动UI,也才能可能准确地使用MVVM模式。

 

下面让我们看代码。

 

页面的设计很简单——Title和ListBox。Load按钮用来加载模拟数据。模拟数据的类型是自定义类Message。

  1. <UserControl x:Class="SilverlightApplicationBBS.Page"
  2.     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
  3.     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
  4.     Width="600" Height="366">
  5.     <StackPanel x:Name="LayoutRoot" Background="LightBlue">
  6.         <!--Title-->
  7.         <StackPanel Orientation="Horizontal">
  8.             <TextBlock Text="Silverlight Mini BBS" FontSize="24" Margin="5" VerticalAlignment="Bottom"/>
  9.             <TextBlock Text="Powered by: 水之真谛" Width="200"  VerticalAlignment="Bottom" Margin="10"/>
  10.             <Button Content="Load"  Height="23" Width="75" VerticalAlignment="Bottom" Margin="10" Click="LoadButton_Click" />
  11.         </StackPanel>
  12.         <!--Content-->
  13.         <ListBox x:Name="listBox" Margin="10" Height="300" />
  14.     </StackPanel>
  15. </UserControl>

自定义Message类:

  1.     public class Message
  2.     {
  3.         public string Title { getset; }
  4.         public string OpenedBy { getset; }
  5.         public string OpenTime { getset; }
  6.         public string Content { getset; }
  7.     }

运行起来是这样:

 

 

 

让我们看看Load按钮的Click事件处理器:

 

  1.         private void LoadButton_Click(object sender, RoutedEventArgs e)
  2.         {
  3.             // 造些假数据。项目中数据来自数据库
  4.             List<Message> msgList = new List<Message>();
  5.             for (int i = 0; i < 30; i++)
  6.             {
  7.                 Message msg = new Message()
  8.                 {
  9.                     Title = "Message Title " + i.ToString(),
  10.                     OpenedBy = (i % 2 == 0) ? "Tom" : "Tim",
  11.                     OpenTime = DateTime.Now.ToShortDateString(),
  12.                     Content = (i % 2 == 0) ? "水之真谛" : @"http://blog.csdn.net/FantasiaX"
  13.                 };
  14.                 msgList.Add(msg);
  15.             }
  16.             this.listBox.ItemsSource = msgList;
  17.         }

点击Load后,效果是这样的:

 

 

咦?怎么显示的是数据类型呢?
是啊!你不给数据穿好“衣服”,人家怎么知道如何show给你呢?
让我们给Message数据穿上一身合适的衣服!也就是给ListBox配上合适的ItemTemplate。注意:ListBox的Item是Message,而不是ListBoxItem控件。当你把一列Message设置为ListBox的ItemsSource时,ListBox会自动为每个Message生成一个容器(ListBoxItem)——WPF中所有ItemsControl都有自己对应的Item容器,比如ListView的Item容器是ListViewItem。特别提醒一点:一个好的数据驱动UI的程序,你完全用不着显式地为ItemsControl添加Item容器,如果你发现有这样的代码,那八成是没理解“数据驱动UI”,或者说又拿WPF当WinForm使了

 

这是添加好DataTemplate后的XAML代码:

  1. <UserControl x:Class="SilverlightApplicationBBS.Page"
  2.     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
  3.     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
  4.     Width="600" Height="366">
  5.     <UserControl.Resources>
  6.         <!--DataTemplate-->
  7.         <DataTemplate x:Key="messageTemplate">
  8.             <StackPanel>
  9.                 <StackPanel Orientation="Horizontal" Height="23">
  10.                     <TextBlock Text="Title:" Width="40" VerticalAlignment="Center" />
  11.                     <TextBox Text="{Binding Path=Title}" Width="180"/>
  12.                     <TextBlock Text="By:" Width="30" VerticalAlignment="Center" />
  13.                     <TextBox Text="{Binding Path=OpenedBy}" Width="80"/>
  14.                     <TextBlock Text="At:" Width="30" VerticalAlignment="Center" />
  15.                     <TextBox Text="{Binding Path=OpenTime}" Width="80"/>
  16.                     <Button Content="Switch" Width="75" Margin="20, 0,0 0" Click="Button_Click"/>
  17.                 </StackPanel>
  18.                 <StackPanel x:Name="detailPanel" Orientation="Horizontal" Height="60" Visibility="Collapsed">
  19.                     <TextBox Margin="40,5,10,5" Text="{Binding Path=Content}" Width="400"/>
  20.                 </StackPanel>
  21.             </StackPanel>
  22.         </DataTemplate>
  23.     </UserControl.Resources>
  24.     <StackPanel x:Name="LayoutRoot" Background="LightBlue">
  25.         <!--Title-->
  26.         <StackPanel Orientation="Horizontal">
  27.             <TextBlock Text="Silverlight Mini BBS" FontSize="24" Margin="5" VerticalAlignment="Bottom"/>
  28.             <TextBlock Text="Powered by: 水之真谛" Width="200"  VerticalAlignment="Bottom" Margin="10"/>
  29.             <Button Content="Load"  Height="23" Width="75" VerticalAlignment="Bottom" Margin="10" Click="LoadButton_Click" />
  30.         </StackPanel>
  31.         <!--Content-->
  32.         <ListBox x:Name="listBox" Margin="10" Height="300" ItemTemplate="{StaticResource messageTemplate}"/>
  33.     </StackPanel>
  34. </UserControl>

点击Load,这回看到的界面就对了!

 

 

然后尝试点击每个Switch按钮——视图能够切换:

 

 

这一点是怎么做到的呢?
原来,秘密是在DataTemplate里Switch按钮的处理函数中:

 

  1.         // 切换视图
  2.         private void Button_Click(object sender, RoutedEventArgs e)
  3.         {
  4.             // Silverlight里的VisualTreeHelper功能受限,所以只能这样做。WPF里的就方便多了。
  5.             Button b = sender as Button;
  6.             StackPanel p = VisualTreeHelper.GetParent(b) as StackPanel;
  7.             p = VisualTreeHelper.GetParent(p) as StackPanel;
  8.             p = p.FindName("detailPanel"as StackPanel;
  9.             if (p.Visibility == Visibility.Collapsed)
  10.             {
  11.                 p.Visibility = Visibility.Visible;
  12.             }
  13.             else
  14.             {
  15.                 p.Visibility = Visibility.Collapsed;
  16.             }
  17.         }

只是Silverlight为了“减肥”,把很多VisualTreeHelper的功能都给砍了,这样我们就只能手动地去找到需要显示/隐藏的UI元素了。

 

你可能会问:那么多记录,每条上都有一个Switch按钮,是不是需要写一个循环,把它们的Click事件与Button_Click函数关联起来呀?

答案是:No!当你把一列数据赋值给ListBox.ItemsSource时,ListBox会按照自己的ItemTemplate(即我们设计的DataTemplate)逐个处理自己的Item。

 

到此,功能就已经实现了。如果觉得UI不是很漂亮,那就交给我们的designer,他们会给整个程序穿上漂亮的外衣。

下面的图是我请团队主力设计师之一Owen进行美化后的结果,请大家欣赏!

 

 

 

最后,祝大家周末快乐!(这里是源码http://download.csdn.net/source/885340,感谢Tom上传!)

 

=====================================================

友情链接:

Owen同学的设计站 http://www.wangkun2008.com/

Owen同学是我们团队里的主力designer之一,我的一些程序就是由Owen同学美化的。谢谢Owen!

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 12
    评论
在移动应用开发中,自动轮播视图是一个非常常见的控件,它可以帮助用户展示多个图片或者内容,使得应用更加生动、丰富。但是在Xamarin中,自动轮播视图并没有原生的控件,需要通过自定义布局来实现。本文将介绍如何使用CarouselView实现支持无限滚动的自动轮播视图。 ## 1. CarouselView简介 CarouselView是一个基于Xamarin.Forms的自定义布局,它可以帮助我们实现类似于ViewPager的效果,支持水平和垂直滚动,并且可以无限滚动。它的主要特点包括: - 支持多种布局方式,包括Stack、Wrap、Grid等。 - 支持水平和垂直滚动,以及无限滚动。 - 支持手势滑动和自动轮播。 - 提供了各种事件,方便我们进行自定义操作。 ## 2. 安装CarouselView 要使用CarouselView,我们首先需要将其添加到我们的项目中。我们可以通过NuGet包管理器来安装CarouselView,具体操作如下: 1. 在Visual Studio中打开我们的移动应用项目。 2. 打开NuGet包管理器,可以通过菜单栏中的“工具”->“NuGet包管理器”->“管理解决方案的NuGet包”打开。 3. 在NuGet包管理器中搜索“CarouselView.FormsPlugin”,并安装它。 安装完成后,我们就可以在项目中使用CarouselView了。 ## 3. 使用CarouselView 在使用CarouselView之前,我们需要在XAML文件中添加CarouselView的命名空间: ```xml xmlns:cv="clr-namespace:CarouselView.FormsPlugin.Abstractions;assembly=CarouselView.FormsPlugin.Abstractions" ``` 然后在我们的布局中添加CarouselView控件: ```xml <cv:CarouselView x:Name="carouselView" ItemsSource="{Binding ImageUrls}" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" Orientation="Horizontal" PositionSelected="OnPositionSelected"> <cv:CarouselView.ItemTemplate> <DataTemplate> <Image Source="{Binding .}" Aspect="AspectFill" /> </DataTemplate> </cv:CarouselView.ItemTemplate> </cv:CarouselView> ``` 上述代码中,我们使用了一个绑定ImageUrls的集合作为CarouselView的数据源,每一个Item都是一个Image控件。我们还可以通过设置HorizontalOptions和VerticalOptions来控制CarouselView的布局方式,设置Orientation来控制滚动的方向。 在代码中,我们可以通过PositionSelected事件来监听当前选中的位置,然后进行自定义操作: ```csharp private void OnPositionSelected(object sender, PositionSelectedEventArgs e) { // Do something } ``` ## 4. 实现无限滚动 上述代码中的CarouselView实现了基本的自动轮播效果,但是它并不能无限滚动。当滚动到最后一个Item时,就会停止滚动,用户需要手动操作才能再次滚动。 要实现无限滚动,我们需要通过自定义布局来实现。具体操作如下: 1. 创建一个新的CarouselView控件,继承自CarouselView控件。 ```csharp public class InfiniteCarouselView : CarouselViewControl { //... } ``` 2. 在控件中实现一个循环滚动的方法,用于在滚动到最后一个Item时将其移动到第一个Item。 ```csharp private void LoopScroll(int position) { if (position == ItemsSource.Count - 1) { Task.Delay(200).ContinueWith(t => { Device.BeginInvokeOnMainThread(() => { this.Position = 0; }); }); } } ``` 3. 在控件的构造函数中监听PositionSelected事件,当滚动到最后一个Item时调用LoopScroll方法。 ```csharp public InfiniteCarouselView() { PositionSelected += (sender, e) => { LoopScroll(e.NewValue); }; } ``` 4. 在页面中使用我们自定义的CarouselView控件。 ```xml <local:InfiniteCarouselView x:Name="carouselView" ItemsSource="{Binding ImageUrls}" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" Orientation="Horizontal"> <cv:CarouselView.ItemTemplate> <DataTemplate> <Image Source="{Binding .}" Aspect="AspectFill" /> </DataTemplate> </cv:CarouselView.ItemTemplate> </local:InfiniteCarouselView> ``` 通过以上步骤,我们就可以实现一个支持无限滚动的自动轮播视图了。完整代码示例可以参考我的Github仓库:https://github.com/wangxizhe/CarouselViewDemo 。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值