Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Horrorble performance using ListViews with nested objects in WPF

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

like image 605
Christian Avatar asked Jul 29 '26 02:07

Christian


1 Answers

All the answers up to now seem to focus on making the UI perform faster, while it seems to me the datacollection that is to blame. I made a similar application and had no performance issues. Do the properties you bind to represent fields or queries?

like image 54
Dabblernl Avatar answered Aug 01 '26 06:08

Dabblernl



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!