Horrorble performance using ListViews with nested objects in WPF

Posted by Christian on Stack Overflow See other posts from Stack Overflow or by Christian
Published on 2011-01-12T09:51:07Z Indexed on 2011/01/12 9:53 UTC
Read the original article Hit count: 312

Filed under:
|
|
|
|

Hi community,

like mentioned in the title I get a horrible performance if I use ListViews with nested objects. My scenario is: Each row of a ListView presents an object of the class Transaction with following attributes:

private int mTransactionID;
private IBTTransactionSender mSender;
private IBTTransactionReceiver mReceiver;
private BTSubstrate mSubstrate;
private double mAmount;
private string mDeliveryNote;
private string mNote;
private DateTime mTransactionDate;
private DateTime mCreationTimestamp;
private BTEmployee mEmployee;
private bool mImported;
private bool mDescendedFromRecurringTransaction;

Each attribute can be accessed by its corresponding property. An ObservableCollection<Transaction> is bound to the ItemsSource of a ListView. The ListView itself looks like the following:

        </ListView.GroupStyle>
        <ListView.View>
            <GridView>

                <GridViewColumn core:SortableListView.SortPropertyName="Transaction.ToSave" Width="80">
                    <GridViewColumnHeader Name="GVCHLoadedToSave" Style="{StaticResource ListViewHeaderStyle}">Speichern</GridViewColumnHeader>
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <Grid>
                                <CheckBox Name="CBListViewItem" IsChecked="{Binding Path=Transaction.ToSave, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></CheckBox>
                            </Grid>
                        </DataTemplate>
                    </GridViewColumn.CellTemplate>
                </GridViewColumn>

                <GridViewColumn core:SortableListView.SortPropertyName="Transaction.TransactionDate" Width="80">
                    <GridViewColumnHeader Name="GVCHLoadedDate" Style="{StaticResource ListViewHeaderStyle}">Datum</GridViewColumnHeader>
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <Grid>
                                <TextBlock Text="{Binding ElementName=DPDate, Path=Text}" Style="{StaticResource GridBlockStyle}"/>
                                <toolkit:DatePicker Name="DPDate" 
                                                                Width="{Binding ElementName=GVCHDate, Path=ActualWidth}"
                                                                SelectedDateFormat="Short" 
                                                                Style="{StaticResource GridEditStyle}" 
                                                                SelectedDate="{Binding Path=Transaction.TransactionDate, Mode=TwoWay}"
                                                                SelectedDateChanged="DPDate_SelectedDateChanged"/>
                            </Grid>
                        </DataTemplate>
                    </GridViewColumn.CellTemplate>
                </GridViewColumn>

                <GridViewColumn core:SortableListView.SortPropertyName="Transaction.Sender.Description" Width="120">
                    <GridViewColumnHeader Name="GVCHLoadedSender" Style="{StaticResource ListViewHeaderStyle}">Von</GridViewColumnHeader>
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <Grid>
                                <TextBlock Text="{Binding Path=Transaction.Sender.Description}" Style="{StaticResource GridBlockStyle}"/>
                                <ComboBox Name="CBSender"
                                                      Width="{Binding ElementName=GVCHSender, Path=ActualWidth}"
                                                      SelectedItem="{Binding Path=Transaction.Sender}"
                                                      DisplayMemberPath="Description"
                                                      Text="{Binding Path=Sender.Description, Mode=OneWay}"
                                                      ItemsSource="{Binding ElementName=Transaction, Path=SenderList}"
                                                      Style="{StaticResource GridEditStyle}">
                                </ComboBox>
                            </Grid>
                        </DataTemplate>
                    </GridViewColumn.CellTemplate>
                </GridViewColumn>

                <GridViewColumn core:SortableListView.SortPropertyName="Transaction.Receiver.Description" Width="120">
                    <GridViewColumnHeader Name="GVCHLoadedReceiver" Style="{StaticResource ListViewHeaderStyle}">Nach</GridViewColumnHeader>
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <Grid>
                                <TextBlock Text="{Binding Path=Transaction.Receiver.Description}" Style="{StaticResource GridBlockStyle}"/>
                                <ComboBox Name="CBReceiver"
                                                      Width="{Binding ElementName=GVCHReceiver, Path=ActualWidth}"
                                                      SelectedItem="{Binding Path=Transaction.Receiver}"
                                                      DisplayMemberPath="Description"
                                                      Text="{Binding Path=Receiver.Description, Mode=OneWay}"
                                                      ItemsSource="{Binding ElementName=Transaction, Path=ReceiverList}"
                                                      Style="{StaticResource GridEditStyle}">
                                </ComboBox>
                            </Grid>
                        </DataTemplate>
                    </GridViewColumn.CellTemplate>
                </GridViewColumn>

                <GridViewColumn core:SortableListView.SortPropertyName="Transaction.Substrate.Description" Width="140">
                    <GridViewColumnHeader Name="GVCHLoadedSubstrate" Style="{StaticResource ListViewHeaderStyle}">Substrat</GridViewColumnHeader>
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <Grid>
                                <TextBlock Text="{Binding Path=Transaction.Substrate.Description}" Style="{StaticResource GridBlockStyle}"/>
                                <ComboBox Name="CBSubstrate"
                                                      Width="{Binding ElementName=GVCHSubstrate, Path=ActualWidth}"
                                                      SelectedItem="{Binding Path=Transaction.Substrate}"
                                                      DisplayMemberPath="Description"
                                                      Text="{Binding Path=Substrate.Description, Mode=OneWay}"
                                                      ItemsSource="{Binding ElementName=Transaction, Path=SubstrateList}"
                                                      Style="{StaticResource GridEditStyle}">
                                </ComboBox>
                            </Grid>
                        </DataTemplate>
                    </GridViewColumn.CellTemplate>
                </GridViewColumn>

                <GridViewColumn core:SortableListView.SortPropertyName="Transaction.Amount" Width="80">
                    <GridViewColumnHeader Name="GVCHLoadedAmount" Style="{StaticResource ListViewHeaderStyle}">Menge [kg]</GridViewColumnHeader>
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <Grid>
                                <TextBlock Text="{Binding Path=Transaction.Amount}" Style="{StaticResource GridBlockStyle}"/>
                                <TextBox Name="TBAmount" Text="{Binding Path=Transaction.Amount, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Width="{Binding ElementName=GVCHAmount, Path=ActualWidth}" Style="{StaticResource GridTextBoxStyle}" />
                            </Grid>
                        </DataTemplate>
                    </GridViewColumn.CellTemplate>
                </GridViewColumn>

                <GridViewColumn core:SortableListView.SortPropertyName="Transaction.DeliveryNote" Width="100">
                    <GridViewColumnHeader Name="GVCHLoadedDeliveryNote" Style="{StaticResource ListViewHeaderStyle}">Lieferschein Nr.</GridViewColumnHeader>
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <Grid>
                                <TextBlock Text="{Binding Path=Transaction.DeliveryNote}" Style="{StaticResource GridBlockStyle}"/>
                                <TextBox Name="TBDeliveryNote" Text="{Binding Path=Transaction.DeliveryNote, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Width="{Binding ElementName=GVCHDeliveryNote, Path=ActualWidth}" Style="{StaticResource GridEditStyle}" />
                            </Grid>
                        </DataTemplate>
                    </GridViewColumn.CellTemplate>
                </GridViewColumn>

                <GridViewColumn core:SortableListView.SortPropertyName="Transaction.Note" Width="190">
                    <GridViewColumnHeader Name="GVCHLoadedNote" Style="{StaticResource ListViewHeaderStyle}">Bemerkung</GridViewColumnHeader>
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <Grid>
                                <TextBlock Text="{Binding Path=Transaction.Note}" Style="{StaticResource GridBlockStyle}"/>
                                <TextBox Name="TBNote" Text="{Binding Path=Transaction.Note, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Width="{Binding ElementName=GVCHNote, Path=ActualWidth}" Style="{StaticResource GridEditStyle}" />
                            </Grid>
                        </DataTemplate>
                    </GridViewColumn.CellTemplate>
                </GridViewColumn>

                <GridViewColumn core:SortableListView.SortPropertyName="Transaction.Employee.LastName" Width="100">
                    <GridViewColumnHeader Name="GVCHLoadedEmployee" Style="{StaticResource ListViewHeaderStyle}">Mitarbeiter</GridViewColumnHeader>
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <Grid>
                                <TextBlock Text="{Binding Path=Transaction.Employee.LastName}" Style="{StaticResource GridBlockStyle}"/>
                                <ComboBox Name="CBEmployee"
                                                      Width="{Binding ElementName=GVCHEmployee, Path=ActualWidth}"
                                                      SelectedItem="{Binding Path=Transaction.Employee}"
                                                      DisplayMemberPath="LastName"
                                                      Text="{Binding Path=Employee.LastName, Mode=OneWay}"
                                                      ItemsSource="{Binding ElementName=Transaction, Path=EmployeeList}"
                                                      Style="{StaticResource GridEditStyle}">
                                </ComboBox>
                            </Grid>
                        </DataTemplate>
                    </GridViewColumn.CellTemplate>
                </GridViewColumn>

            </GridView>
        </ListView.View>
    </ListView>

As you can see in the screenshot the user got the possibility to change the values of the transaction attributes with comboboxes.

Ok now to my problem. If I click on the "Laden" button the application will load about 150 entries in the ObservableCollection<Transaction>. Before I fill the collection I set the ItemsSource of the ListView to null and after filling I bind the collection to the ItemsSource once again. The loading itself takes a few milliseconds, but the rendering of the filled collection takes a long time (150 entries = about 20 sec). I tested to delete all Comboboxes out of the xaml and i got a better performance, because I don't have to fill the ComboBoxes for each row. But I need to have these comboboxes for modifing the attributes of the Transaction.

Does anybody know how to improve the performance?

THX

© Stack Overflow or respective owner

Related posts about wpf

Related posts about Performance