C# WinRT/XAML中的FlipView数据模板特性

C# WinRT/XAML中的FlipView数据模板特性,c#,mvvm,winrt-xaml,C#,Mvvm,Winrt Xaml,我一直面临着一个问题,即使用我们的资产虚拟化FlipView控件,以获得无缝的选择体验。我们使用Nuget上提供的VariableGrid模板从头开始更新UI,使应用程序在展示我们的礼品目录时看起来像windows应用商店 FlipView控件应该展示我们的大图像和一条小缩略图,以便用户可以查看产品的不同选项,对于最初的几个项目,它可以正常工作,但是缩略图项目过了一段时间就开始混淆了-我对项目如何在flipview控件中排列和绑定感到有点困惑,我想知道您是否可以解释一下这个问题?我在控件中使用了

我一直面临着一个问题,即使用我们的资产虚拟化FlipView控件,以获得无缝的选择体验。我们使用Nuget上提供的VariableGrid模板从头开始更新UI,使应用程序在展示我们的礼品目录时看起来像windows应用商店

FlipView控件应该展示我们的大图像和一条小缩略图,以便用户可以查看产品的不同选项,对于最初的几个项目,它可以正常工作,但是缩略图项目过了一段时间就开始混淆了-我对项目如何在flipview控件中排列和绑定感到有点困惑,我想知道您是否可以解释一下这个问题?我在控件中使用了一个数据模板,将图像添加到flipview中原始项目图像旁边的wrappanel中。我不确定如何管理wrappanel,我已经附上了使用它的部分的代码

    private async Task PopulateThumbnails()
    {
        var thumbnailWrapGrid = RecurseChildren<WrapPanel>(flipView).ElementAt(flipView.SelectedIndex);
        if (thumbnailWrapGrid == null) return;

        thumbnailWrapGrid.Width = Window.Current.Bounds.Width - (420 + Window.Current.Bounds.Height); // 420 is experiencepanel + backmargin. images are square scaled to height
        var thisItem = (this.flipView.SelectedItem as PGItemViewModel);
        thumbnailWrapGrid.Children.Clear();
        foreach (var img in thisItem.ItemPhoto)
            await AddChildren(img, thumbnailWrapGrid);
    }

    private async Task AddChildren(KeyValuePair<string, ItemPhoto> img, WrapPanel panel)
    {
        var imgbitmap = new Image() { Source = new BitmapImage(new Uri(img.Value.LocalOrRemoteLocation)) };
        imgbitmap.Tapped += imgbitmap_Tapped;
        panel.Children.Add(imgbitmap);
    }

    void imgbitmap_Tapped(object sender, TappedRoutedEventArgs e)
    {
        var zoomImage = RecurseChildren<Image>(flipView).ElementAt(flipView.SelectedIndex);
        zoomImage.Source = (sender as Image).Source;
    }

   public static IEnumerable<T> RecurseChildren<T>(DependencyObject root) where T : UIElement
    {
        if (root is T)
        {
            yield return root as T;
        }

        if (root != null)
        {
            var count = VisualTreeHelper.GetChildrenCount(root);


            for (var idx = 0; idx < count; idx++)
            {
                foreach (var child in RecurseChildren<T>(VisualTreeHelper.GetChild(root, idx)))
                {
                    yield return child;
                }
            }
        }
    }
//XAML

<StackPanel x:Name="ImageHost" Margin="0" Orientation="Horizontal" Loaded="PopulateThumbnails" GotFocus="InFocus">
<Image x:Name="image" Source="{Binding BigPhoto}" Margin="0" HorizontalAlignment="Left"/>
<ScrollViewer Margin="0,135,0,0">
<Controls:WrapPanel x:Name="thumbnailWrap" Margin="0">
<Controls:WrapPanel.Transitions>
<TransitionCollection/>
</Controls:WrapPanel.Transitions>
</Controls:WrapPanel>
</ScrollViewer>
</StackPanel>

将FlipView.ItemsPanel更改为使用StackPanel而不是VirtualzingStackPanel似乎可行,但这对大量项目不起作用,因为它们会占用大量内存。下面是示例模板

FlipView.ItemsPanel="{StaticResource ItemsPanelStyleTemplate}"


    <ItemsPanelTemplate x:Key="ItemsPanelStyleTemplate">
        <StackPanel AreScrollSnapPointsRegular="True" Orientation="Horizontal" />
    </ItemsPanelTemplate>

另一个解决方法来自MikeOrmond@MSFT

class MikesFlipView : FlipView
{

protected override void PrepareContainerForItemOverride
    (Windows.UI.Xaml.DependencyObject element, object item)
{
  base.PrepareContainerForItemOverride(element, item);

  UserControl userControl = GetFirstChildOfType<UserControl>(element);

  if (userControl != null)
  {
    userControl.DataContext = item;

    var panel = GetFirstChildOfType<WrapPanel>(userControl);
    panel.Children.Clear();

    foreach (var img in ((ItemViewModel)item).Photo)
      AddChildren(img, panel);
  }
}

// this method is used to add children to the controls inside FlipView
private void AddChildren(KeyValuePair<string, ItemPhoto> img, WrapPanel panel)
{
  ...
}

private static T GetFirstChildOfType<T>(DependencyObject dobj)
 where T : DependencyObject
{
  T retVal = null;
  int numKids = VisualTreeHelper.GetChildrenCount(dobj);
  for (int i = 0; i < numKids; ++i)
  {
    DependencyObject child = VisualTreeHelper.GetChild(dobj, i);
    if (child is T)
    { 
      retVal = (T)child;
    }
    else
    {
      retVal = GetFirstChildOfType<T>(child);
    }

    if (retVal != null)
    {
      break;
    }
  }

  return retVal;
} 
}

从发布前几天开始,RTM中的VirtualzingStackPanel似乎出现了一个问题,类似于这个问题。当我找到一个令人满意的解决方法时,我将更新这个问题。