Results 1 to 6 of 6

Thread: [RESOLVED] WinForms BeginUpdate() equivalent in WPF?

  1. #1

    Thread Starter
    New Member
    Join Date
    Mar 2010
    Posts
    10

    Resolved [RESOLVED] WinForms BeginUpdate() equivalent in WPF?

    Ok.. let's say you have the following code:
    Code:
    for (int i = 0; i < 91001; i++)
    {
    Listbox.Items.Add(i);
    }
    In WinForms I'd do:
    Code:
    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

  2. #2
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: WinForms BeginUpdate() equivalent in WPF?

    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.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  3. #3
    Pro Grammar chris128's Avatar
    Join Date
    Jun 2007
    Location
    England
    Posts
    7,604

    Re: WinForms BeginUpdate() equivalent in WPF?

    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.
    My free .NET Windows API library (Version 2.2 Released 12/06/2011)

    Blog: cjwdev.wordpress.com
    Web: www.cjwdev.co.uk


  4. #4

    Thread Starter
    New Member
    Join Date
    Mar 2010
    Posts
    10

    Re: WinForms BeginUpdate() equivalent in WPF?

    Quote Originally Posted by jmcilhinney View Post
    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.

    Quote Originally Posted by chris128 View Post
    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.
    Last edited by Lith; May 7th, 2010 at 04:16 PM.

  5. #5
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: WinForms BeginUpdate() equivalent in WPF?

    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:
    1. Public Class Form1
    2.  
    3.     Private letters As Char() = "abcdefghijklmnopqrstuvwxyz".ToCharArray()
    4.     Private rng As New Random
    5.     Private max As Integer = letters.Length
    6.  
    7.     Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    8.         Dim watch = Stopwatch.StartNew()
    9.  
    10.         For count = 1 To 100000
    11.             Me.ListBox1.Items.Add(Me.letters(Me.rng.Next(Me.max)))
    12.         Next
    13.  
    14.         Console.WriteLine(watch.Elapsed)
    15.     End Sub
    16.  
    17. End Class
    00:00:14.6206819
    00:00:13.3435931
    00:00:14.3321844
    vb.net Code:
    1. Public Class Form1
    2.  
    3.     Private letters As Char() = "abcdefghijklmnopqrstuvwxyz".ToCharArray()
    4.     Private rng As New Random
    5.     Private max As Integer = letters.Length
    6.  
    7.     Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    8.         Dim watch = Stopwatch.StartNew()
    9.  
    10.         Me.ListBox1.BeginUpdate()
    11.  
    12.         For count = 1 To 100000
    13.             Me.ListBox1.Items.Add(Me.letters(Me.rng.Next(Me.max)))
    14.         Next
    15.  
    16.         Me.ListBox1.EndUpdate()
    17.  
    18.         Console.WriteLine(watch.Elapsed)
    19.     End Sub
    20.  
    21. End Class
    00:00:00.8258245
    00:00:00.9750567
    00:00:00.8716296
    vb.net Code:
    1. Public Class Form1
    2.  
    3.     Private letters As Char() = "abcdefghijklmnopqrstuvwxyz".ToCharArray()
    4.     Private rng As New Random
    5.     Private max As Integer = letters.Length
    6.  
    7.     Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    8.         Dim watch = Stopwatch.StartNew()
    9.  
    10.         Dim upperBound = 100000 - 1
    11.         Dim items(upperBound) As Object
    12.  
    13.         For index = 0 To upperBound
    14.             items(index) = Me.letters(Me.rng.Next(Me.max))
    15.         Next
    16.  
    17.         Me.ListBox1.Items.AddRange(items)
    18.  
    19.         Console.WriteLine(watch.Elapsed)
    20.     End Sub
    21.  
    22. End Class
    00:00:00.9451726
    00:00:00.8333862
    00:00:00.8349755
    vb.net Code:
    1. Class MainWindow
    2.  
    3.     Private letters As Char() = "abcdefghijklmnopqrstuvwxyz".ToCharArray()
    4.     Private rng As New Random
    5.     Private max As Integer = letters.Length
    6.  
    7.     Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles Button1.Click
    8.         Dim watch = Stopwatch.StartNew()
    9.  
    10.         For count = 1 To 100000
    11.             Me.ListBox1.Items.Add(Me.letters(Me.rng.Next(Me.max)))
    12.         Next
    13.  
    14.         Console.WriteLine(watch.Elapsed)
    15.     End Sub
    16.  
    17. End Class
    00:00:00.8518833
    00:00:00.8643582
    00:00:00.8179867
    vb.net Code:
    1. Class MainWindow
    2.  
    3.     Private letters As Char() = "abcdefghijklmnopqrstuvwxyz".ToCharArray()
    4.     Private rng As New Random
    5.     Private max As Integer = letters.Length
    6.  
    7.     Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles Button1.Click
    8.         Dim watch = Stopwatch.StartNew()
    9.  
    10.         Me.ListBox1.BeginInit()
    11.  
    12.         For count = 1 To 100000
    13.             Me.ListBox1.Items.Add(Me.letters(Me.rng.Next(Me.max)))
    14.         Next
    15.  
    16.         Me.ListBox1.EndInit()
    17.  
    18.         Console.WriteLine(watch.Elapsed)
    19.     End Sub
    20.  
    21. End Class
    00:00:00.1255790
    00:00:00.1265229
    00:00:00.1444075
    vb.net Code:
    1. Class MainWindow
    2.  
    3.     Private letters As Char() = "abcdefghijklmnopqrstuvwxyz".ToCharArray()
    4.     Private rng As New Random
    5.     Private max As Integer = letters.Length
    6.  
    7.     Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles Button1.Click
    8.         Dim watch = Stopwatch.StartNew()
    9.  
    10.         Dim upperBound = 100000 - 1
    11.         Dim items(upperBound) As Object
    12.  
    13.         For index = 0 To upperBound
    14.             items(index) = Me.letters(Me.rng.Next(Me.max))
    15.         Next
    16.  
    17.         Me.ListBox1.ItemsSource = items
    18.  
    19.         Console.WriteLine(watch.Elapsed)
    20.     End Sub
    21.  
    22. 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.
    Last edited by jmcilhinney; May 8th, 2010 at 12:56 AM.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  6. #6

    Thread Starter
    New Member
    Join Date
    Mar 2010
    Posts
    10

    Re: WinForms BeginUpdate() equivalent in WPF?

    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:
    Code:
            <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 =).
    Last edited by Lith; May 8th, 2010 at 03:37 PM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width