【问题标题】:Lazy load FlipView content延迟加载 FlipView 内容
【发布时间】:2021-05-22 17:36:35
【问题描述】:

我在 UWP 中有一个带有 2 个选项卡的 FlipView,我认为它在 WPF 中的行为类似于 TabControl。我正在关注 Ruben Bartelink 在lazy load tab control contents 提供的帖子。但我的问题是,当我进入屏幕时,我看到断点击中了所有用户控件的所有 InitilizeComponent()。请帮忙。

这是我的 xaml:

<FlipView 
    x:Name="FlipViewStatus" Grid.Row="2"
    Style="{StaticResource FlipViewStyleNoPageButtons}"
    Background="Transparent"
    SelectedIndex="{x:Bind ViewModel.SelectedTabIndex, Mode=TwoWay}">
    <FlipView.ItemContainerStyle>
        <Style TargetType="FlipViewItem">
            <Setter Property="Padding" Value="2 4 4 2"/>
        </Style>
    </FlipView.ItemContainerStyle>
    <FlipViewItem 
        x:Name="FlipViewItemOngoing" 
        Content="{x:Bind ViewModel.VmOnGoingRuns,Mode=OneWay}">
        <FlipViewItem.ContentTemplate>
            <DataTemplate x:DataType="model:VmOnGoingRunsCollection">
                <Grid x:Name="FlipViewItemOngoingGrid" 
                      PointerWheelChanged="PointerWheelIgnore">
                    <local:StatusRunsView 
                        x:Name="StatusOngoingRuns"
                        RecentSpecimenRuns="{x:Bind OnGoingRunsCollection, 
                                                    Mode=OneWay}"
                        IsLoadingRuns="{x:Bind IsLoadingOngoingRuns, 
                                               Mode=OneWay}"/>
                </Grid>
            </DataTemplate>
        </FlipViewItem.ContentTemplate>
    </FlipViewItem>
    
    <FlipViewItem 
        x:Name="FlipViewItemSampleOutput" 
        Content="{x:Bind ViewModel.OutputStatusViewModel,Mode=OneWay}">
        <FlipViewItem.ContentTemplate>
            <DataTemplate>
                <Grid x:Name="FlipViewItemSampleOutputGrid" 
                      PointerWheelChanged="PointerWheelIgnore">
                    <local:StatusSampleOutputView x:Name="StatusSampleOutput" 
                                                  ViewModel="{Binding}"/>
                </Grid>
            </DataTemplate>
        </FlipViewItem.ContentTemplate>
    </FlipViewItem>
</FlipView>

在与此 FlipView 关联的 ViewModel 中,我有一些代码如下。

public class ViewModel : BindableBaseThreadSafe
{
    private ISampleOutputStatusViewModel _outputStatusViewModel;
    public ISampleOutputStatusViewModel OutputStatusViewModel
    {
        get => _outputStatusViewModel;
        set => Set(ref _outputStatusViewModel, value);
    }

    public int SelectedTabIndex
    {
        //I am debugging here and the tab index is correct
        get => _selectedTabIndex; 
        set
        {
            if (Set(ref _selectedTabIndex, value))
            {
                LoadData((StatusList)_selectedTabIndex)
                    .Await(OnErrorLoadingData);
            }
        }
    }

    public ViewModel()
    {
        VmOnGoingRuns = 
            lifetimeScope.Resolve<VmOnGoingRunsCollection>();

        VmOnGoingRuns.OnGoingRunsCollection = 
            new ObservableCollection<VmStatusSpecimen>();
    }

    //The listname enum is being set from xaml.
    private async Task LoadData(StatusList listName)
    {
        switch (listName)
        {
            case StatusList.OngoingRuns:
                await LoadOngoingRuns();
                break;

            // This code executes correctly when the user selects the 
            // Output tab in the FlipView. 
            case StatusList.Output:
                {
                    OutputStatusViewModel = _lifetimeScope
                        .Resolve<ISampleOutputStatusViewModel>();

                    break;
                }
        }
    }
}

我的问题是,当我导航到此 FlipView 页面时,我看到断点命中 StatusSampleOutputView.xaml.cs InitilizeComponent()。我希望它延迟加载,换句话说,只有当用户选择 StatusSampleOutputView 时,我才希望加载此视图。请帮助我做错了什么。,

【问题讨论】:

  • 来自 uwp 的 FlipView 控件与 wpf 中的 TabControl 不同,你不能指望它像你在 wpf 应用程序中使用 TabControl 那样实现你的要求。此外,FlipView 派生自 ItemsControl,它有一个名为 UI virtualization 的延迟加载。这意味着代表项目的 UI 元素是按需创建的。
  • 对于绑定到多个项目集合的项目控件,当项目接近滚动到视图中(几页之外)时,框架可以为这些项目生成 UI 并缓存它们。因此,您可以尝试创建多个项目(例如 100 个项目),然后检查框架是否同时为所有项目生成 UI。
  • 谢谢你的解释,我现在明白了。
  • 我已将我的评论转换为答案,您可以标记有用的答案,这将有助于其他面临相同问题的人。

标签: wpf uwp tabcontrol flipview


【解决方案1】:

来自 uwp 的 FlipView 控件与 wpf 中的 TabControl 不同,你不能指望它像你在 wpf 应用程序中使用 TabControl 那样实现你的要求。此外,FlipView 派生自 ItemsControl,它有一个称为 UI virtualization 的延迟加载。这意味着代表项目的 UI 元素是按需创建的。

对于绑定到多个项目集合的项目控件,当项目接近滚动到视图中(几页之外)时,框架可以为这些项目生成 UI 并缓存它们。因此,您可以尝试创建多个项目(例如 100 个项目),然后检查框架是否同时为所有项目生成 UI。

【讨论】:

  • 这就是我解决问题的方法。 UWP 中有一个名为 x:Load 的属性。每当用户更改选项卡时,我都会从我的 ViewModel 设置此属性。
  • 很高兴得知您的问题已得到解决。您可以发布您的解决方案并标记它,这将有助于其他面临相同问题的人。
  • 我一定会这样做的。
【解决方案2】:

ContentControl 可以有延迟加载,你可以试试以下方法:

  1. 将实际项目视图模型包装成具有单一属性的轻量级虚拟视图模型
  2. 在 FlipView 项目模板中放置 ContentControl 并将其绑定到该属性
  3. 为 ContentControl 创建 EmptyWhenNullTemplateSelector,当数据存在时为 null 和实际数据模板返回 new DataTemplate()
  4. 当 FlipView 的选择发生变化时,加载数据并设置实际视图模型

【讨论】:

    【解决方案3】:

    Uwp 在 UI 元素上有一个名为 x:Load 的属性。在我的特定情况下,如果我想延迟加载选项卡,我在 ViewModel 中有一个实现 INotifyPropertyChanged 的​​ bool 属性,我会在 true 或 false 之间切换。另一方面,如果要在 xaml.cs 中设置 UIElement 的 x:Load 属性,则需要执行类似的操作。

    if (sender is FrameworkElement frameworkElement)
            {
                // This loads the child UI elements when the expander is expanded
                frameworkElement.FindName("ListViewPanels");
            }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-29
      • 1970-01-01
      • 1970-01-01
      • 2011-04-20
      • 2011-03-17
      • 2014-02-08
      相关资源
      最近更新 更多