MVVM performance: do not dispose View when using D

2019-06-27 13:36发布

问题:

I have performance issue and I need help to overcome it.

There is a window which displays different views (user controls) using ContentControl. I have bunch of ViewModels and corresponding UserControl bound via DataTemplate:

<DataTemplate DataType="{x:Type l:ViewModelPageA}">
    <l:UserControlPageA/>
</DataTemplate>
<DataTemplate DataType="{x:Type l:ViewModelPageB}">
    <l:UserControlPageBk/>
</DataTemplate>

This creates views depending on which ViewModel is displayed now.

One of UserControl has quite comprehensive ListView (a lot of bindings, triggers, etc). When switching to this user control ViewModel there is a significant delay (over a second).

I looked into virtualization already, but it doesn't looks like my concern: ViewModel persist between switches, there are only 100 of items and there is no performance problem after user control is rendered. Actually there is a small delay when using PgUpPgDown, which looks to me like some sort of virtualization (ListViewItems are not created for invisible items) .

So problem is with initial view loading. It takes too much time to load. And will take more, as only 50% of bindings/triggers are done so far. Without items loading is nearly instant.

In winforms e.g. without MVVM I kept views (forms) in memory and switches between them. Maybe this is what I should do in wpf too (to keep view of this problematic ViewModel alive)?

Question: considering said about (if there are no better alternatives to improve performance) how can I reuse view when using MVVM and data templating?


Predicting comments "show us some code" here is something to gives you idea about ListView complication:

<ListView x:Name="listView" ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem}" IsSynchronizedWithCurrentItem="True">
    <ListView.Resources>
        <!-- cell template, there are many of such -->
        <DataTemplate x:Key="cellTemplateA">
            <StackPanel>
                <StackPanel Orientation="Horizontal">
                    <Button CommandParameter="{Binding}" Command="{Binding DataContext.CommandA, ElementName=listView}"
                            Visibility="{Binding IsCommandAVisible}" l:ButtonBehavior.SelectListViewItemOnFocus="True">
                        <Viewbox>
                            <Grid>
                                <!-- some simple vector graphic -->
                                <Path Width="13" Height="13" ...
                                      Visibility="{Binding IsExpanded, Converter={l:BoolToVisibilityHiddenConverter}, ConverterParameter=CollapsedInverted}"/>
                                <Path Width="13" Height="13" ...
                                      Visibility="{Binding IsExpanded, Converter={l:BoolToVisibilityHiddenConverter}, ConverterParameter=Collapsed}"/>
                            </Grid>
                        </Viewbox>
                    </Button>
                    <!-- more of such buttons -->
                </StackPanel>
                <!-- more of elements using visibility binding -->
            </StackPanel>
        </DataTemplate>
    </ListView.Resources>
    <ListView.View>
        <GridView>
            <!-- many columns using different cell templates -->
            <GridViewColumn Header="Date" CellTemplate="{StaticResource cellTemplateDate}"/>
        </GridView>
    </ListView.View>
    <ListView.ItemContainerStyle>
        <Style TargetType="ListViewItem">
            <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
            <Setter Property="VerticalContentAlignment" Value="Top"/>
            <Style.Triggers>
            <!-- and a lot of triggers here -->
            </Style.Triggers>
        </Style>
    </ListView.ItemContainerStyle>
</ListView>
标签: c# wpf mvvm