zoukankan      html  css  js  c++  java
  • Observable 示例之 Windows Phone 列表内项目逐个加载

    在写 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 控件的全部代码:

        <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 下载

  • 相关阅读:
    为什么基于TCP的应用需要心跳包(TCP keep-alive原理分析)
    「DDoS攻击」兴风作浪,教你如何有效防护!
    你还敢乱粘贴吗?
    TODO git如何去掉烦人的merge?
    Git修改已经push到远程的commit信息
    Oracle删除唯一索引失败提示ORA-01418:指定的索引不存在 ORACLE
    mybatis逆向生成代码 [ERROR] No plugin found for prefix 'mybatis-generator' in the current project and in the plugin groups
    MySQL 中 redo log、undo log、binlog 的总结
    VATT: Transformers for Multimodal Self-Supervised Learning from Raw Video, Audio and Text
    OPT: Omni-Perception Pre-Trainer for Cross-Modal Understanding and Generation
  • 原文地址:https://www.cnblogs.com/hebeiDGL/p/3410988.html
Copyright © 2011-2022 走看看