c# - Windows 手机 8 : Add FrameworkElement to PanoramaItem from code behind

标签 c# xaml windows-phone-8

当我从全景图背后的代码将 FrameworkElements 添加到 PanoramaItem 时,会“选择”panoramaItem,从而导致非常糟糕的用户体验。

我做了一个小型测试项目,重现了问题。

主页仅包含包含三个项目的全景图:

<Grid x:Name="LayoutRoot" Background="Transparent">
    <phone:Panorama Name="m_Panorama">
        <phone:PanoramaItem Header="Item 1" 
                            Name="m_Item1">
            <StackPanel Orientation="Vertical" Name="m_Stack1">
            </StackPanel>
        </phone:PanoramaItem>
        <phone:PanoramaItem Header="Item 2" 
                            Name="m_Item2">
            <StackPanel Orientation="Vertical" Name="m_Stack2">
            </StackPanel>
        </phone:PanoramaItem>
        <phone:PanoramaItem Header="Item 3" 
                            Name="m_Item3">
            <StackPanel Orientation="Vertical" Name="m_Stack3">
            </StackPanel>
        </phone:PanoramaItem>            
    </phone:Panorama>
</Grid>

后面的代码使用 DispatcherTimer 开始将元素添加到 PanoramaItems:

public partial class MainPage : PhoneApplicationPage
{
  public MainPage()
  {
    InitializeComponent();
  }

  protected override void OnNavigatedTo(NavigationEventArgs e)
  {
    base.OnNavigatedTo(e);
    if (e.NavigationMode == NavigationMode.New){
      StartDelayed(UpdateItem1, 1000);
      StartDelayed(UpdateItem2, 1000);
      StartDelayed(UpdateItem3, 1000);
    }
  }

  private void AddTextblock(StackPanel stackPanel, string text, bool animate)
  {
    TextBlock tb = new TextBlock();
    tb.Text = text;
    stackPanel.Children.Add(tb);

    if (animate){
      tb.Measure(new Size(double.MaxValue, double.MaxValue));
      tb.UpdateLayout();

      Storyboard sb = new Storyboard();
      DoubleAnimation anim = new DoubleAnimation();
      anim.Duration = new Duration(TimeSpan.FromMilliseconds(500));
      anim.From = 0;
      anim.To = tb.DesiredSize.Width;
      sb.Children.Add(anim);
      Storyboard.SetTarget(anim, tb);
      Storyboard.SetTargetProperty(anim, new PropertyPath("Width"));
      sb.Begin();
    }
  }

  private async void UpdateItem1(object sender, EventArgs e)
  {
    while (true){
      m_Stack1.Children.Clear();
      for (int i=0; i<10; i++){
        await Task.Delay(500);
        AddTextblock(m_Stack1, "This is item 1", false);
      }
    }
  }

  private async void UpdateItem2(object sender, EventArgs e)
  {
    while (true){
      m_Stack2.Children.Clear();
      for (int i=0; i<10; i++){
        await Task.Delay(1000);
        AddTextblock(m_Stack2, "This is item 2", false);
      }
    }
  }

  private async void UpdateItem3(object sender, EventArgs e)
  {
    while (true){
      m_Stack3.Children.Clear();
      for (int i=0; i<10; i++){
        await Task.Delay(1500);
        AddTextblock(m_Stack3, "This is item 3", false);
      }
    }
  }

  private static void StartDelayed(EventHandler handler, int milliseconds)
  {
    DispatcherTimer timer = new DispatcherTimer();
    timer.Interval = TimeSpan.FromMilliseconds(milliseconds);
    if (handler != null)
      timer.Tick += new EventHandler(handler);
    timer.Tick += new EventHandler(OnLoadedTimerTick);
    timer.Start();
  } // StartDelayed

  private static void OnLoadedTimerTick(object sender, EventArgs e)
  {
    DispatcherTimer timer = sender as DispatcherTimer;
    if (timer != null)
      timer.Stop();
  } // OnLoadedTimerTick
}

如果缓慢滚动全景图,就会出现问题:一旦将一个项目添加到堆栈面板,全景图就会重新定位到包含添加元素的 PanoramaItem。

我的问题是:我做错了什么?如何避免全景图选择panoramaItem?

最佳答案

一个快速的解决方案是将 StackPanel 封装在固定大小的容器中。

例如

<phone:PanoramaItem Header="Item 1" Name="m_Item1">
    <ScrollViewer Height="1024">
        <StackPanel Orientation="Vertical" Name="m_Stack1"/>
    </ScrollViewer>
</phone:PanoramaItem>

我认为正在发生的事情是,它会动态调整元素及其容器的大小,从而导致您在水平滚动到下一个全景项目时看到的抖动 Action 。如果您愿意,您可以将该 ScrollViewer 的高度绑定(bind)到屏幕的高度,以实现最佳使用。

关于c# - Windows 手机 8 : Add FrameworkElement to PanoramaItem from code behind,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25016287/

相关文章:

Word Interop 中的 C# 行间距

xaml - Xamarin 检测输入键 MVVM

html - 在 Windows Phone 8 的 cordova 应用程序中禁用用户缩放

c# - 将委托(delegate)转换为 System.Action

c# - 如何在 C# 中翻转 Sprite

c# - Roslyn 中的代理缓存行为更改

c# - 如何获取 HTTP Web 请求以返回完整源代码

滚动到顶部/底部时,Wpf 禁用重复按钮

wpf - 如何根据 ContentControl 的当前内容的 DataType 自动使用 DataTemplate

c# - 'await' 运算符只能在异步 lambda 表达式中使用 Windows Phone 8