不要每次使用DataTemplate/DataType创建新视图

5

我有类似这样的东西:

<Window>
    <Window.Resources>
       <DataTemplate DataType="{x:Type local:VM1}">
          <!-- View 1 Here -->
       </DataTemplate>

       <DataTemplate DataType="{x:Type local:VM2}">
          <!-- View 2 here -->
       </DataTemplate>
    <Window.Resources>

    <ContentPresenter Content="{Binding}"/>
</Window>

这将自动在绑定不同的viewmodel时替换视图,非常方便。
然而,我有一个带TabControl和多个子视图的视图。每个子视图都有几个可视部分,由自定义xml文件配置(复杂的业务情况)。每次创建此视图时,都会解析xml文件,这会导致小延迟(1-2秒)。足以引起烦恼并使UI感觉迟缓。
是否有一种方法可以在不销毁和重新创建视图的情况下使用DataTemplate模式?如果可能的话,我宁愿不更改viewmodel。

你的问题缺少很多信息。为什么每次都要解析XML文件?XML文件数据如何影响您正在创建的视图?您能给出至少一个简化的场景吗? - Dmitry
3
回答这个问题并不需要做那些事情。我不想重新构建视图或视图模型。我只是想问一下,在绑定视图模型时是否有一种方法可以使用DataTemplates而不会每次都销毁视图。 - ConditionRacer
2个回答

2

对于这种情况,最简单的解决方案是始终保留这两个视图,并更改哪一个可见。您可以使用转换器根据数据上下文的类型更改可见性。

<View1 Visibility="{Binding Converter={StaticResource TypeToVisibilityConverter, ConverterParameter=VM1}" />
<View2 Visibility="{Binding Converter={StaticResource TypeToVisibilityConverter, ConverterParameter=VM2}" />

转换器将检查类型是否与参数匹配,如果匹配则返回Visible,否则返回Collapsed。


1
这种方法可能会导致在具有大量绑定的复杂视图中出现一些性能问题。实际上,一旦视图变得可见并且可视树被创建,即使在折叠状态下,绑定也将被刷新。 - Dmitry

0
你可以将你的虚拟机封装到一个额外的类中。你的数据模板将决定包装类的类型,但真正的实现将通过这个包装类的属性来暴露。当这个属性改变时,数据模板不会重新加载,但所有绑定都会刷新。
包装类:
public class WrapperVM1:INotifyPropertyChanged
{
    public Content VM1 { get{...} set{...} }
}

public class WrapperVM2:INotifyPropertyChanged
{
    public Content VM2 { get{...} set{...} }
}

现在你的数据模板将描述包装类的表示:

<DataTemplate DataType="{x:Type local:WrapperVM1}">
   <TextBlock Text={Binding Content.SomPropertyInVM1}"/>
</DataTemplate>

<DataTemplate DataType="{x:Type local:WrapperVM2}">
   <TextBlock Text={Binding Content.SomPropertyInVM2}"/>
</DataTemplate>

正如您所看到的,如果您使用新的 VM 实例替换包装器的 Content 属性,则不会重新创建视图,但所有绑定都将更新。但是,如果您需要切换到其他类型的 VM,则必须使用相应的包装器替换 Wrapper 类。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接