# .NET and More > WPF, WCF, WF >  [RESOLVED] WinForms BeginUpdate() equivalent in WPF?

## Lith

Ok.. let's say you have the following code:


```
for (int i = 0; i < 91001; i++)
{
Listbox.Items.Add(i);
}
```

In WinForms I'd do:


```
Listbox.BeginUpdate();
for (int i = 0; i < 91001; i++)
{
Listbox.Items.Add(i);
}
ListBox.EndUpdate();
```

that would take perhaps, 3 seconds to execute... now in WPF the problem lies in the fact that I do not know how to stop the drawing until all items are added before drawing everything in one go.

The thing is, I need to load files (1~3 MB big, containing words/URLS on each line) into a Listbox, now when you just use the Listbox.Items.Add it would take centuries to load, let alone the resources it would consume.

So, if anyone could help me, I'd be grateful.

P.S: I am using the Bureau Black theme from http://wpf.codeplex.com/wikipage?title=WPF%20Themes

----------


## jmcilhinney

I've never really used WPF and I don't know the answer to your question.  What I did do is open the documentation for the WPF ListBox control and see that it has a BeginInit method, so my first guess would be to use that.

That said, I think your best bet would be to add all the data to an array or collection and then assign it to the ItemSource of the ListBox.  That would be somewhat like using AddRange once instead of Add many times in WinForms.

----------


## chris128

Yeah the preferred way to do it in WPF would be to add all of the items to a List/Array and then just assign that list to the ItemsSource property of the listbox. Give that a go and see what sort of performance you get.

----------


## Lith

> I've never really used WPF and I don't know the answer to your question.  What I did do is open the documentation for the WPF ListBox control and see that it has a BeginInit method, so my first guess would be to use that.
> 
> That said, I think your best bet would be to add all the data to an array or collection and then assign it to the ItemSource of the ListBox.  That would be somewhat like using AddRange once instead of Add many times in WinForms.


Want to know something funny? The first thing I tried was the BeginInit method, even funnier, it was as slow as I would programmatically start a Loop to add everything to the listbox.

I went on and tried the ItemSource too, but I realized that it was definitely not the same as AddRange because it still took as much time as doing it via a Loop.




> Yeah the preferred way to do it in WPF would be to add all of the items to a List/Array and then just assign that list to the ItemsSource property of the listbox. Give that a go and see what sort of performance you get.


Done it, and the performance is as bad as using a Loop to add everything to the listbox.


My apologizes, I should've mentioned the methods I've used before posting >___>....

Anyway, the main problem I am continuously facing is the fact that when I time (using the System.Diagnostics.StopWatch Class) everything; it takes less than 100 milliseconds to do, but now comes the scary part, it needs to draw everything in the listbox and it takes like 5 seconds to draw 2001 items in the listbox... it doesn't sound that scary right? ... until I try adding 90 000 items to the listbox... well let's say it takes like 3 seconds in WinForms, whilst the app gets stuck when doing it in WPF.

----------


## jmcilhinney

I just did some testing on the following code snippets.  The first three are WinForms and the last three are WPF.  I ran each one three times and the elapsed times are shown below.
vb.net Code:
Public Class Form1
     Private letters As Char() = "abcdefghijklmnopqrstuvwxyz".ToCharArray()
    Private rng As New Random
    Private max As Integer = letters.Length
     Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim watch = Stopwatch.StartNew()
         For count = 1 To 100000
            Me.ListBox1.Items.Add(Me.letters(Me.rng.Next(Me.max)))
        Next
         Console.WriteLine(watch.Elapsed)
    End Sub
 End Class



> 00:00:14.6206819
> 00:00:13.3435931
> 00:00:14.3321844



vb.net Code:
Public Class Form1
     Private letters As Char() = "abcdefghijklmnopqrstuvwxyz".ToCharArray()
    Private rng As New Random
    Private max As Integer = letters.Length
     Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim watch = Stopwatch.StartNew()
         Me.ListBox1.BeginUpdate()
         For count = 1 To 100000
            Me.ListBox1.Items.Add(Me.letters(Me.rng.Next(Me.max)))
        Next
         Me.ListBox1.EndUpdate()
         Console.WriteLine(watch.Elapsed)
    End Sub
 End Class



> 00:00:00.8258245
> 00:00:00.9750567
> 00:00:00.8716296



vb.net Code:
Public Class Form1
     Private letters As Char() = "abcdefghijklmnopqrstuvwxyz".ToCharArray()
    Private rng As New Random
    Private max As Integer = letters.Length
     Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim watch = Stopwatch.StartNew()
         Dim upperBound = 100000 - 1
        Dim items(upperBound) As Object
         For index = 0 To upperBound
            items(index) = Me.letters(Me.rng.Next(Me.max))
        Next
         Me.ListBox1.Items.AddRange(items)
         Console.WriteLine(watch.Elapsed)
    End Sub
 End Class



> 00:00:00.9451726
> 00:00:00.8333862
> 00:00:00.8349755



vb.net Code:
Class MainWindow 
     Private letters As Char() = "abcdefghijklmnopqrstuvwxyz".ToCharArray()
    Private rng As New Random
    Private max As Integer = letters.Length
     Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles Button1.Click
        Dim watch = Stopwatch.StartNew()
         For count = 1 To 100000
            Me.ListBox1.Items.Add(Me.letters(Me.rng.Next(Me.max)))
        Next
         Console.WriteLine(watch.Elapsed)
    End Sub
 End Class



> 00:00:00.8518833
> 00:00:00.8643582
> 00:00:00.8179867



vb.net Code:
Class MainWindow 
     Private letters As Char() = "abcdefghijklmnopqrstuvwxyz".ToCharArray()
    Private rng As New Random
    Private max As Integer = letters.Length
     Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles Button1.Click
        Dim watch = Stopwatch.StartNew()
         Me.ListBox1.BeginInit()
         For count = 1 To 100000
            Me.ListBox1.Items.Add(Me.letters(Me.rng.Next(Me.max)))
        Next
         Me.ListBox1.EndInit()
         Console.WriteLine(watch.Elapsed)
    End Sub
 End Class



> 00:00:00.1255790
> 00:00:00.1265229
> 00:00:00.1444075



vb.net Code:
Class MainWindow 
     Private letters As Char() = "abcdefghijklmnopqrstuvwxyz".ToCharArray()
    Private rng As New Random
    Private max As Integer = letters.Length
     Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles Button1.Click
        Dim watch = Stopwatch.StartNew()
         Dim upperBound = 100000 - 1
        Dim items(upperBound) As Object
         For index = 0 To upperBound
            items(index) = Me.letters(Me.rng.Next(Me.max))
        Next
         Me.ListBox1.ItemsSource = items
         Console.WriteLine(watch.Elapsed)
    End Sub
 End Class



> 00:00:00.0110180
> 00:00:00.0094633
> 00:00:00.0258997


I think that those results pretty much speak for themselves.  Using BeginInit and EndInit resulted in about an 8-fold reduction in the time.  Setting the ItemsSource resulted in about a 10-fold reduction in time over that.  I can't comment on your results because I haven't seen your code, but it sounds like just drawing your items is the problem, not that they are being drawn multiple times.

----------


## Lith

Ok, Wow, stupid me....

What you confirmed is entirely correct, what I forgot to do is to test the whole thing out in a new project in WPF without using a theme... And yeah, I just tried it... and yup, 100 000 items get added to the list in less than 3 seconds without a theme.

As I mentioned in my first post; I use the Expression Light theme from http://wpf.codeplex.com/wikipage?title=WPF%20Themes

Now, this means that the problem apparently lies in the theme....





*OK, problem solved....*
Apparently this was the wrong-doer in the Theme:


```
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type ListBox}">
                    <Grid>
                        <Border x:Name="Border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="2" Background="{DynamicResource ControlBackgroundBrush}" />
                        <ScrollViewer Margin="1" Style="{DynamicResource NuclearScrollViewer}" Focusable="false" Background="{x:Null}">
                            <StackPanel Margin="1,1,1,1" IsItemsHost="true" />
                        </ScrollViewer>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsEnabled" Value="false">
                            <Setter Property="Background" Value="{DynamicResource DisabledBackgroundBrush}" TargetName="Border" />
                            <Setter Property="BorderBrush" Value="{DynamicResource DisabledBorderBrush}" TargetName="Border" />
                        </Trigger>
                        <Trigger Property="IsGrouping" Value="true">
                            <Setter Property="ScrollViewer.CanContentScroll" Value="false" />
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
```

I removed that part of the XAML script and now everything works like a charm.

Thank you VERY MUCH, I freakin' love you =D. No, but seriously, thanks for the help and confirming everything, really appreciate the help you've given me here =).

----------

