0
votes

After several weeks of trying to improve the performance of my application I'm asking the question here:

Scenario: A View is created when the user selects a Person out of a DataGrid. The View contains a ListView as menu and a ContentControl where custom UserControls are displayed.

My problem occurs when the DataContext of the view is set - it takes 31 (!!!) seconds to finish the InitializeComponent-Method when set in the constructor (see image below). Constructor for view

However, if I don't set the DataContext to the ViewModel, as shown in the image above, the method is finished in the blink of an eye.

I already tried to optimize my XAML and paid attention to the performance of every control but it did not help.

My class-structur of the important ViewModels for the View is as follows:

  • PersonViewModel : ViewModelBase (used when a normal person is openend)
  • InteressentViewModel : PersonViewModel
  • StudentViewModel : InteressentViewModel

In my view I have bindings on Properties and values of the ViewModel like Collections, simple values like Strings, and so on. For the simple values the binding is set to the Context Property loaded from EF.

My Question: What could be the reason that setting the DataContext takes so much time?

EDIT 1: It also takes so long when I set the DataContext after the Control is Loaded, in the "Loaded" Event.

EDIT 2: Image of Profiler: profiler This is how it looks, when I set the DataContext in the Loaded event (Time is needed for AppCode).

When I set it in the Constructor, the InitializeComponent takes ~30secs and the Profiler states the time is needed for parsing (see comments). Constructor of ViewModel is finished after 0,5 secs in Debug-Mode.

EDIT 3: this is how my constructor of the Student-ViewModel looks like:

public StudentViewModel_v2(T_StudentInVertiefung student) : base(student.T_Interessent)
        {
        // Simple Initialisations
        // loading the context object from the DataBase to a T_StudentInVertiefung Object from the viewModel
        _Student = student;
        ... some more code

        // List initialisations
        ... about 20 ObservableCollections

        // thesis values
        AvailableThesisStates = new ObservableCollection<T_Abschlussarbeitsstatus>();
        AvailableGrades = new ObservableCollection<T_Gesamtpraedikat>();
        AvailableLecturers = new ObservableCollection<T_Vortragender>();

        // set the type of person
        Typ = PersonTyp.STUDENT;
        // Load data values
        // test, if a connection is possible
        if (IngeniumEducationEntities.TestConnection())
        {
            // available options
            // loading values for ComboBox Selection
            #region available options
            AvailableStates = new List<T_Personenstatus>(_dbContext.
                T_Personenstatus.OrderBy(s => s.Bezeichnung));

            #endregion
        }

        // commands
        ... several command initialisations
    }

the class itself is derived from another ViewModel where the constructor looks about the same. Calling the constructor is finished after ~0,5s in DebugMode.

The Binding in the View looks like this:

<TextBox Text="{Binding Person.Vorname, UpdateSourceTrigger=LostFocus}" />

For each type of person (normal, student, alumni, e.g.) different views are available. To bind to a column from the database, e.g. the first name, I put the Binding on the Context-Property stored in the ViewModel like in the code above.

What I forgot say is that it doesn't takes much time everytime when opening a new view. Sometimes it's finished right away and anothertime it takes ~30s.

1
You can use visual studio diagnostics tools/perfview to find out caveat - Dipen Shah
If you want to do it by yourself then: Step 1: Run it in Release mode Step 2: Use stop watch to pin point where is leg coming from Step 3: Repeat step 2 until you reach code which is consuming CPU time Step 4: Improve performance of your code and measure it Step 5: Still feel the pain? post your code on Stackoverflow with whatever you've done so far for someone to guide you - Dipen Shah
Are there properties which have a long running getter, e.g. returning values recalculated on each call of the getter? What about the constructor of your viewmodel? How much time takes it to run the constructor of the viewmodel? - Steffen R.
using DependencyObject instead of INotifyPropertyChanged can also speed up runtime. also Debug mode is very slower than **Release mode **. try some breakpoints in viewmodel callbacks to see everything is executed once (or at least no a hundred times!!) - Bizhan
I agree with @Steffen, this smacks of properties serializing in data from a database or something. Can you try stubbing all your data? Also do you having any very large lists anywhere? This can happen when you template items in a ListBox (et al) and then accidentally break the virtualization. - Mark Feldman

1 Answers

1
votes

If you moved the datacontext assignment to Loaded eventhandler and the performance hit is moving to Loaded event too, then you have a long running data access in your properties which let the binding process slow down.

Try to load the data from database asynchronously before/in parallel and change your properties (getter) to present only already loaded data, e.g. stored/cached data in a backing field of your view model.

Check your data access to the database too. Maybe you can improve the database access too by adding proper indexes on the involved tables.