【问题标题】:Reusing tab content with DataTemplate使用 DataTemplate 重用选项卡内容
【发布时间】:2019-02-06 07:46:26
【问题描述】:

我有一个选项卡控件,其中选项卡是在运行时创建的。选项卡的内容将是几个用户控件之一,每个控件都包含数百个其他控件。由于创建这些用户控件需要很长时间,因此我试图找到一种方法来重用它们,而不是为每个选项卡创建一个新实例。

我正在使用 DataTemplate 设置标签页内容,如下所示:

<DataTemplate>
    <ScrollViewer Content="{Binding Content}" />
</DataTemplate>

Content 是我想在选项卡中显示的视图的视图模型。

在其他地方,我使用数据模板将每个视图模型映射到一个视图,例如

<DataTemplate DataType="{x:Type vm:MyViewModel1}">
    <ctl:CacheContentControl ContentType="{x:Type ctl:MyView1}" />
</DataTemplate>

<DataTemplate DataType="{x:Type vm:MyViewModel2}">
    <ctl:CacheContentControl ContentType="{x:Type ctl:MyView2}" />
</DataTemplate>

CacheContentControl 是我用于缓存的 ContentControl 的包装器:

public class CacheContentControl : ContentControl
{
    private static Dictionary<Type, Control> cache = new Dictionary<Type, Control>();

    public CacheContentControl()
    {
        Unloaded += CacheContentControl_Unloaded;
    }

    private void CacheContentControl_Unloaded(object sender, RoutedEventArgs e)
    {
        Content = null;
    }

    private Type _contentType;
    public Type ContentType
    {
        get { return _contentType; }
        set
        {
            _contentType = value;
            Content = GetView(_contentType);  
        }
    }

    public Control GetView(Type type)
    {
        if (!cache.ContainsKey(type))
        {
            cache.Add(type, (Control)Activator.CreateInstance(type));
        }

        return cache[type];
    }
}

这确保 DataTemplate 在创建新实例之前首先检查缓存以查看它是否可以重用控件。

这适用于创建的任何新标签。第一个选项卡与预期的一样慢,因为它需要创建初始控件,但使用相同控件的所有后续选项卡几乎立即加载。我遇到的问题是,当我单击返回上一个选项卡时,控件不再出现并且选项卡为空白。

我猜这是因为我不能在同一个表单上多次显示同一个控件实例,这是有道理的。我已经能够通过为我的 CacheContentControl 处理 IsVisibleChanged 事件来解决它,如下所示:

    private void CacheContentControl_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
    {
        if (IsVisible && ContentType != null)
        {
            Control ctl = GetView(_contentType);
            ctl.DataContext = DataContext;
            Content = ctl;
        }
        else
        {
            Content = null;
        }
    }

When a tab loses focus it removes the control, the tab that receives focus can then retrieve the control from the cache which seems to work.

问题是速度又变慢了,我不知道为什么。显然,可以毫不拖延地将控件实例从一个选项卡移动到另一个选项卡,因为每次我创建一个新选项卡时都会这样做。 DataTemplate 必须做一些不同的事情来更改控件的父级?

【问题讨论】:

    标签: c# wpf mvvm datatemplate


    【解决方案1】:

    我不确定您是否需要缓存您的用户控件,因为 WPF 在很大程度上为您完成了这项工作。

    在按类型键入的 DataTemplate 中的常规方法是不使用 ContentControl,而只是将 UserControl 作为模板。

     <DataTemplate x:Key=“MyViewmodelType”>
    <MyViewControl />
    </DataTemplate>
    

    TabControl 将有一个 ContentControl,它的 Content 设置为适用的任何 ViewModel,WPF 将使用为该类型指定的 DataTemplate 自动呈现它并设置 DataContext。

    我已经构建了大量的 WPF 视图,这些视图是按照上面概述的更简单的方法使用 DataTemplates 呈现的,而不会遇到任何严重的性能问题,我认为您可以通过简单地将 ContentControl.Content 绑定到您的 ViewModel 实例并让 WPF 处理来安全地开始开发使用上面更简单的 DataTemplate 方法进行渲染。

    【讨论】:

      猜你喜欢
      • 2020-01-25
      • 1970-01-01
      • 2019-10-20
      • 1970-01-01
      • 2016-12-28
      • 2014-12-13
      • 1970-01-01
      • 1970-01-01
      • 2016-12-11
      相关资源
      最近更新 更多