Observable 示例之 Windows Phone 列表内项目逐个加载_移动开发_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > 移动开发 > Observable 示例之 Windows Phone 列表内项目逐个加载

Observable 示例之 Windows Phone 列表内项目逐个加载

 2013/11/6 18:10:57  段博琼  博客园  我要评论(0)
  • 摘要:在写Windowsphone应用性能优化(一)的时候,在ListBox的项加载的时候,添加了一些简单的动画。其实在WindowsPhone的应用中使用Blend设计动画是很容易的,并且在程序的交互中,增加一些动画效果,用户会感觉用户体验非常的好,从而提升了用户对应用的印象评分。本文的demo演示如何逐项的加载列表中的每一项。对于延时迭代加载列表中的项,通常会考虑使用DispatherTimer,但是如果设计的逻辑较多,需要的代码量会比较多,并且不好维护。这里使用Rx
  • 标签:Windows 项目

 

在写 Windows phone 应用性能优化(一)的时候,在 ListBox 的项加载的时候,添加了一些简单的动画。

其实在 Windows Phone 的应用中使用 Blend 设计动画是很容易的,并且在程序的交互中,增加一些动画

效果,用户会感觉用户体验非常的好,从而提升了用户对应用的印象评分。

 

本文的 demo 演示如何逐项的加载列表中的每一项。对于延时迭代加载列表中的项,通常会考虑使用 DispatherTimer,

但是如果设计的逻辑较多,需要的代码量会比较多,并且不好维护。这里使用 Rx(Reactive Extensions) 中的

Observable 类进行对 IObservable<T> 的创建。在 Rx 中 IObservable<T> (可观察队列)和 IObserver<T> (观察者)

是两个核心的元素,我研究了一段时间,感觉它在  .NET 平台是可以大有作为的,它的使用并不难,很多操作使用是以 LINQ

的扩展方法而使用的,重点是理解 (IObservable)的 “推”数据 和 (IEnumerable)的 “拉”数据的 数据源数据流向的不同。

以后还会继续研究的。之前翻译的有关 Rx 一篇文章

 

 

 

这个示例在页面中使用一个 Pivot 控件,两个 PivotItem 项都是使用 ListBox 作为模版,区别是:

1)第一个 PivotItem 项中的 ItemsPanel 模版使用默认的,在第二个 PivotItem 中

的 ListBox 中, 把 ItemsPanel 设置为了 WrapPanel,从而使 Item 可以流动布局:

 <ListBox ItemsSource="{Binding}" >
     <ListBox.ItemsPanel>
         <ItemsPanelTemplate>
             <Controls:WrapPanel />
         </ItemsPanelTemplate>
     </ListBox.ItemsPanel>


2)两个 ListBox 中的 ItemTemplate 中的 StackPanel 在触发 Loaded 事件时,开始的动画不同。

 

MainPage 页面中 Pivot 控件的全部代码:

class="code_img_closed" src="/Upload/Images/2013110618/0015B68B3C38AA5B.gif" alt="" />logs_code_hide('c6e25af8-7e10-4521-a049-c51757d22e71',event)" src="/Upload/Images/2013110618/2B1B950FA3DF188F.gif" alt="" />
    <phone:Pivot SelectionChanged="Pivot_SelectionChanged">
            <phone:PivotItem  Header="Stack">
                <ListBox ItemsSource="{Binding}" >
                    <ListBox.ItemTemplate>
                        <DataTemplate>
                            <StackPanel x:Name="stack" Orientation="Horizontal" Margin="10,30,0,0">
                                <StackPanel.Triggers>
                                    <EventTrigger RoutedEvent="StackPanel.Loaded">
                                        <BeginStoryboard>
                                            <Storyboard x:Name="Storyboard1">
                                                <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Projection).(PlaneProjection.RotationX)" Storyboard.TargetName="stack">
                                                    <EasingDoubleKeyFrame KeyTime="0" Value="-180"/>
                                                    <EasingDoubleKeyFrame KeyTime="0:0:3" Value="0">
                                                        <EasingDoubleKeyFrame.EasingFunction>
                                                            <QuinticEase EasingMode="EaseOut"/>
                                                        </EasingDoubleKeyFrame.EasingFunction>
                                                    </EasingDoubleKeyFrame>
                                                </DoubleAnimationUsingKeyFrames>
                                                <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Projection).(PlaneProjection.RotationY)" Storyboard.TargetName="stack">
                                                    <EasingDoubleKeyFrame KeyTime="0" Value="106"/>
                                                    <EasingDoubleKeyFrame KeyTime="0:0:3" Value="0">
                                                        <EasingDoubleKeyFrame.EasingFunction>
                                                            <QuinticEase EasingMode="EaseOut"/>
                                                        </EasingDoubleKeyFrame.EasingFunction>
                                                    </EasingDoubleKeyFrame>
                                                </DoubleAnimationUsingKeyFrames>
                                                <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Projection).(PlaneProjection.RotationZ)" Storyboard.TargetName="stack">
                                                    <EasingDoubleKeyFrame KeyTime="0" Value="0"/>
                                                    <EasingDoubleKeyFrame KeyTime="0:0:3" Value="0">
                                                        <EasingDoubleKeyFrame.EasingFunction>
                                                            <QuinticEase EasingMode="EaseOut"/>
                                                        </EasingDoubleKeyFrame.EasingFunction>
                                                    </EasingDoubleKeyFrame>
                                                </DoubleAnimationUsingKeyFrames>
                                                <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateX)" Storyboard.TargetName="stack">
                                                    <EasingDoubleKeyFrame KeyTime="0" Value="246"/>
                                                    <EasingDoubleKeyFrame KeyTime="0:0:3" Value="0">
                                                        <EasingDoubleKeyFrame.EasingFunction>
                                                            <QuinticEase EasingMode="EaseOut"/>
                                                        </EasingDoubleKeyFrame.EasingFunction>
                                                    </EasingDoubleKeyFrame>
                                                </DoubleAnimationUsingKeyFrames>
                                                <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.ScaleX)" Storyboard.TargetName="stack">
                                                    <EasingDoubleKeyFrame KeyTime="0" Value="0.4"/>
                                                    <EasingDoubleKeyFrame KeyTime="0:0:3" Value="1">
                                                        <EasingDoubleKeyFrame.EasingFunction>
                                                            <QuinticEase EasingMode="EaseOut"/>
                                                        </EasingDoubleKeyFrame.EasingFunction>
                                                    </EasingDoubleKeyFrame>
                                                </DoubleAnimationUsingKeyFrames>
                                                <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.ScaleY)" Storyboard.TargetName="stack">
                                                    <EasingDoubleKeyFrame KeyTime="0" Value="0.4"/>
                                                    <EasingDoubleKeyFrame KeyTime="0:0:3" Value="1">
                                                        <EasingDoubleKeyFrame.EasingFunction>
                                                            <QuinticEase EasingMode="EaseOut"/>
                                                        </EasingDoubleKeyFrame.EasingFunction>
                                                    </EasingDoubleKeyFrame>
                                                </DoubleAnimationUsingKeyFrames>
                                            </Storyboard>
                                        </BeginStoryboard>
                                    </EventTrigger>
                                </StackPanel.Triggers>
                                <StackPanel.RenderTransform>
                                    <CompositeTransform/>
                                </StackPanel.RenderTransform>
                                <StackPanel.Projection>
                                    <PlaneProjection/>
                                </StackPanel.Projection>
                                <Image VerticalAlignment="Top" Source="{Binding Photo}" Width="150"/>
                                <TextBlock Text="{Binding Title}" Width="250" Foreground="Wheat" FontSize="25" Margin="10,0,0,0" TextWrapping="Wrap"/>
                            </StackPanel>
                        </DataTemplate>
                    </ListBox.ItemTemplate>
                </ListBox>
            </phone:PivotItem>
            <phone:PivotItem  Header="Wrap">
                <ListBox ItemsSource="{Binding}" >
                    <ListBox.ItemsPanel>
                        <ItemsPanelTemplate>
                            <Controls:WrapPanel />
                        </ItemsPanelTemplate>
                    </ListBox.ItemsPanel>
                    <ListBox.ItemTemplate>
                        <DataTemplate>
                            <StackPanel x:Name="stack" Orientation="Horizontal" Margin="10,30,0,0">
                                <StackPanel.Triggers>
                                    <EventTrigger RoutedEvent="StackPanel.Loaded">
                                        <BeginStoryboard>
                                            <Storyboard x:Name="Storyboard1">
                                                <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Projection).(PlaneProjection.CenterOfRotationX)" Storyboard.TargetName="stack">
                                                    <EasingDoubleKeyFrame KeyTime="0" Value="1"/>
                                                    <EasingDoubleKeyFrame KeyTime="0:0:2" Value="1">
                                                        <EasingDoubleKeyFrame.EasingFunction>
                                                            <QuarticEase EasingMode="EaseOut"/>
                                                        </EasingDoubleKeyFrame.EasingFunction>
                                                    </EasingDoubleKeyFrame>
                                                </DoubleAnimationUsingKeyFrames>
                                                <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Projection).(PlaneProjection.RotationY)" Storyboard.TargetName="stack">
                                                    <EasingDoubleKeyFrame KeyTime="0" Value="96"/>
                                                    <EasingDoubleKeyFrame KeyTime="0:0:2" Value="0">
                                                        <EasingDoubleKeyFrame.EasingFunction>
                                                            <QuarticEase EasingMode="EaseOut"/>
                                                        </EasingDoubleKeyFrame.EasingFunction>
                                                    </EasingDoubleKeyFrame>
                                                </DoubleAnimationUsingKeyFrames>
                                            </Storyboard>
                                        </BeginStoryboard>
                                    </EventTrigger>
                                </StackPanel.Triggers>
                                <StackPanel.Projection>
                                    <PlaneProjection/>
                                </StackPanel.Projection>
                                <Image VerticalAlignment="Top" Source="{Binding Photo}" Width="200"/>
                            </StackPanel>
                        </DataTemplate>
                    </ListBox.ItemTemplate>
                </ListBox>
            </phone:PivotItem>
        </phone:Pivot>
View Code


程序的运行效果:

 

在 MainPage 的 C# 页面的主要代码就不贴出来了,和 Windows phone 应用性能优化(一) 中的代码基本相同。

 

重点的代码,是当 Pivot 触发  Pivot_SelectionChanged 事件的时候,逐项加载 ObservableCollection 集合:

  private void Pivot_SelectionChanged(object sender, SelectionChangedEventArgs e)
  {
      ObservableCollection<News> NewsList2 = new ObservableCollection<News>();
      this.DataContext = NewsList2;

      #region 实现 1
      //IObservable<long> obser = Observable.Interval(TimeSpan.FromSeconds(0.3)).ObserveOnDispatcher();

      //obser.Subscribe((i) =>
      //{
          
      //    NewsList2.Add(NewsList[(int)i]);
      //});
      #endregion


      #region 实现 2

      // 方法含义:
      // GenerateWithTime(初始值, 循环条件, 传递给 Observer‘观察者’的值, 延迟时间, 迭代)
      //
      // 类似于 for循环:for(初始值;循环条件;迭代)
      IObservable<int> source = Observable.GenerateWithTime(0,
          i => i < NewsList.Count,
          i => i,
          i => TimeSpan.FromSeconds(.3),
          i => i + 1);
      
      // 在 Dispather 线程,每次接受 source 传递来的 i 值,即下面的 x
      source.ObserveOnDispatcher().Subscribe(x =>
      {
          NewsList2.Add(NewsList[x]);
          Debug.WriteLine(x);
      });

      #endregion
  }

 

把上面的 Observable.GenerateWithTime(...); 方法可以理解成:

  for (int i = 0; i < count; i++)
  {
      // 当然,Observable 的时间延迟是在异步线程中完成的
      Thread.Sleep(TimeSpan.FromSeconds(.3));

      // 逻辑
  }


 

 

工程 demo 下载

发表评论
用户名: 匿名