8

I hava a mvvm wpf application that worked properly all until one moment when it freezes and causes massive memory leak. Solution files: Google Disk Solution Link

The application uses local mdf file, uses Mahhaps , and some additional references (for example one for displaying gifs)

enter image description here

This is the method call in the View model that is making the issue, the assignment of the Contacts with await is making the issue - this is used in one other view model where it makes no any issues, even here it was working all right until one moment.

public async  void OnLoad()
        {
            IsRefreshEnabled = false;
            IsRefreshProgressActive = true;
            Contacts =await Task.Run(() => _repository.GetContactsAsync()) ;
            IsRefreshEnabled = true;
            IsRefreshProgressActive = false;
        }

This is the way the View is rendered

<DataGrid SelectedItem="{Binding Contact}" AutoGenerateColumns="True" ItemsSource="{Binding Path=Contacts, Mode=TwoWay}" Style="{StaticResource AzureDataGrid}"  x:Name="dataGridCodeBehind"  Margin="10,54,521,0" VerticalAlignment="Top"  HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch" ColumnWidth="*">
            <DataGrid.ColumnHeaderStyle>
                <Style TargetType="DataGridColumnHeader">
                    <Setter Property="FontSize" Value="10"/>
                </Style>
            </DataGrid.ColumnHeaderStyle>
        </DataGrid>

I tried removing the libraries, for gifs(the gifs are not shown in this view in the other view which is not making any issues there).

The same call to the repository - to fetch the Contacts data I have on one other view and it is not making any problems.

This Contacts view was working good all until sudden.

I tried to debug but the debugger does not even come to the code.

After loading some data into the db I get a freeze.

The freeze is made by the OnLoad method from the ContactsViewModel - this call to the repository is used on one other ViewModel where it has no any issues - it returns the data quickly

ContactsViewModel code:

using Digital_Data_House_Bulk_Mailer.Commands;
using Digital_Data_House_Bulk_Mailer.Model;
using Digital_Data_House_Bulk_Mailer.Repository;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;

namespace Digital_Data_House_Bulk_Mailer.ViewModel
{
    class ContactsViewModel : INotifyPropertyChanged
    {
        private Contact _contact;

        private IContactRepository _repository = new ContactRepository();

        public event PropertyChangedEventHandler PropertyChanged = delegate { };

        public static event EventHandler<PropertyChangedEventArgs> StaticPropertyChanged;

        private static void NotifyStaticPropertyChanged(string propertyName)
        {
            if (StaticPropertyChanged != null)
                StaticPropertyChanged(null, new PropertyChangedEventArgs(propertyName));
        }

        public RelayCommand UpdateCommand { get; set; }

        public RelayCommand LoadCommand { get; set; }

        public RelayCommand DeleteCommand { get; set; }

        public RelayCommand DeleteAllContactsCommand { get; set; }

        public RelayCommand RecreateFiltersCommand { get; set; }

        private ObservableCollection<Contact> _contacts;

        public ObservableCollection<Contact> Contacts
        {
            get { return _contacts; }
            set
            {
                _contacts = value;
                PropertyChanged(this, new PropertyChangedEventArgs("Contacts"));
                //used in case of static Contacts property
                //NotifyStaticPropertyChanged("Contacts"); 
            }
        }


        public Contact Contact
        {
            get { return _contact; }
            set
            {
                _contact = value;
                DeleteCommand.RaiseCanExecuteChanged();
                UpdateCommand.RaiseCanExecuteChanged();
                PropertyChanged(this, new PropertyChangedEventArgs("Contact"));
            }
        }

        private bool _isRefreshEnabled=true;
        public bool IsRefreshEnabled
        {
            get { return _isRefreshEnabled; }
            set
            {
                _isRefreshEnabled = value;
                PropertyChanged(this, new PropertyChangedEventArgs("IsRefreshEnabled"));
            }
        }

        private bool _isRefreshProgressActive = false;
        public bool IsRefreshProgressActive
        {
            get { return _isRefreshProgressActive; }
            set
            {
                _isRefreshProgressActive = value;
                PropertyChanged(this, new PropertyChangedEventArgs("IsRefreshProgressActive"));
            }
        }

        public ContactsViewModel()
        {
            DeleteCommand = new RelayCommand(OnDelete, CanDelete);
            UpdateCommand = new RelayCommand(OnUpdate, CanUpdate);
            LoadCommand = new RelayCommand(OnLoad, CanLoad);
            DeleteAllContactsCommand = new RelayCommand(OnDeleteAllContacts, CanDeleteAllContacts);
            RecreateFiltersCommand = new RelayCommand(OnRecreateFilters, CanRecreateFilters);
            OnLoad();
        }

        public bool CanRecreateFilters()
        {
            return true;
        }

        public async void OnRecreateFilters()
        {
            IsRefreshProgressActive = true;
            await Task.Run(() => _repository.ResetFilters());
            IsRefreshProgressActive = false;
        }

        public async void OnDeleteAllContacts()
        {
            MessageBoxResult messageBoxResult = System.Windows.MessageBox.Show("Are you sure?", "DELETE ALL EXISTING CONTACTS", System.Windows.MessageBoxButton.YesNo);
            if (messageBoxResult == MessageBoxResult.Yes)
            {
                IsRefreshProgressActive = true;
                await Task.Run(() => _repository.DeleteAllContacts());
                IsRefreshProgressActive = false;
            }
        }

        public bool CanDeleteAllContacts()
        {
            return true;
        }


        private void OnDelete()
        {
            MessageBoxResult messageBoxResult = System.Windows.MessageBox.Show("Are you sure?", "Delete Contact Confirmation", System.Windows.MessageBoxButton.YesNo);
            if (messageBoxResult == MessageBoxResult.Yes)
            {
                _repository.DeleteContactAsync(Contact);
                Contacts.Remove(Contact);
            }
        }

        private bool CanDelete()
        {          
            if (Contact != null )
            {
                return true;
            }
            return false;
        }

        private  void OnUpdate()
        {
             _repository.AddContactAsync(Contact);

        }

        private bool CanUpdate()
        {
            if (Contact != null )
            {
                return true;
            }
            return false;
        }


        public async  void OnLoad()
        {
            IsRefreshEnabled = false;
            IsRefreshProgressActive = true;
            Contacts =await Task.Run(() => _repository.GetContactsAsync()) ;
            IsRefreshEnabled = true;
            IsRefreshProgressActive = false;
        }

        private  ObservableCollection<Contact> GetContactsAsync()
        {
            return _repository.GetContactsAsync();
        }

        public bool CanLoad()
        {
            return true;
        }

    }
}

ContactRepository class:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Digital_Data_House_Bulk_Mailer.Model;
using System.Data.Entity;
using System.Collections.ObjectModel;
using System.Data.Entity.Migrations;
using System.Collections;
using System.Data.Entity.Core.Objects;
using System.Data.SqlClient;

namespace Digital_Data_House_Bulk_Mailer.Repository
{
    class ContactRepository : IContactRepository
    {
        digital_datahouse_bulk_mailerEntities db = null;

        public ContactRepository()
        {
            db = new digital_datahouse_bulk_mailerEntities();
        }

        public string SELECT_ALL { get { return "Select All"; } private set { } }


        public  ObservableCollection<StateFilter> GetStates()
        {

            ObservableCollection<StateFilter> stateFilters = new ObservableCollection<StateFilter>();

            foreach (StateFilter state in db.StateFilters.ToList() )
            {
                db.Entry<StateFilter>(state).Reload();
                stateFilters.Add(state);
            }



            return stateFilters;
        }

        public ObservableCollection<CountyFilter> GetCounties()
        {
            ObservableCollection<CountyFilter> countyFilters = new ObservableCollection<CountyFilter>();

            foreach (CountyFilter county in db.CountyFilters.ToList())
            {
                db.Entry<CountyFilter>(county).Reload();
                countyFilters.Add(county);
            }

            return countyFilters;
        }

        public ObservableCollection<GenderFilter> GetGenders()
        {
            ObservableCollection<GenderFilter> genderFilters = new ObservableCollection<GenderFilter>();

            foreach (GenderFilter gender in db.GenderFilters.ToList())
            {
                db.Entry<GenderFilter>(gender).Reload();
                genderFilters.Add(gender);
            }

            return genderFilters;
        }

        public ObservableCollection<IndustryFilter> GetIndustries()
        {
            ObservableCollection<IndustryFilter> industryFilters = new ObservableCollection<IndustryFilter>();

            foreach (IndustryFilter industry in db.IndustryFilters.ToList())
            {
                db.Entry<IndustryFilter>(industry).Reload();
                industryFilters.Add(industry);
            }

            return industryFilters;
        }

        public ObservableCollection<IsContactedFilter> GetIsContacted()
        {
            ObservableCollection<IsContactedFilter> isContactedFilters = new ObservableCollection<IsContactedFilter>();

            foreach (IsContactedFilter isContacted in db.IsContactedFilters.ToList())
            {
                db.Entry<IsContactedFilter>(isContacted).Reload();
                isContactedFilters.Add(isContacted);
            }

            return isContactedFilters;
        }

        public ObservableCollection<SicCodeDescriptionFilter> GetSicCodeDescriptions()
        {
            ObservableCollection<SicCodeDescriptionFilter> sicCodeDescriptionFilters = new ObservableCollection<SicCodeDescriptionFilter>();

            foreach (SicCodeDescriptionFilter sicCodeDescriptionFilter in db.SicCodeDescriptionFilters.ToList())
            {
                db.Entry<SicCodeDescriptionFilter>(sicCodeDescriptionFilter).Reload();
                sicCodeDescriptionFilters.Add(sicCodeDescriptionFilter);
            }

            return sicCodeDescriptionFilters;
        }



        public void AddContactAsync(Contact contact)
        {
            if (contact != null)
            {
                db.Contacts.AddOrUpdate(contact);
                db.SaveChangesAsync();
            }
        }

        public void DeleteContactAsync(Contact contact)
        {
            if (contact != null)
            {
                db.Contacts.Remove(contact);
                db.SaveChangesAsync();
            }
        }

        public void UpdateContactAsync(Contact contact)
        {
            if (contact != null)
            {
                db.Contacts.AddOrUpdate(contact);
                db.SaveChangesAsync();
            }
        }

        public ObservableCollection<Contact> GetContactsAsync()
        {

            db = new digital_datahouse_bulk_mailerEntities();

            ObservableCollection<Contact> contacts = new ObservableCollection<Contact>();

            foreach (var contact in db.Contacts.ToList())
            {
                contacts.Add(contact);
            }
            return contacts;
        }

        public ObservableCollection<Contact> FilterContacts(ObservableCollection<StateFilter> states, ObservableCollection<CountyFilter> counties, 
            ObservableCollection<GenderFilter> genders, ObservableCollection<IndustryFilter> industries, ObservableCollection<IsContactedFilter> contacted, 
            ObservableCollection<SicCodeDescriptionFilter> codes, bool hasWebsite)
        {

            db = new digital_datahouse_bulk_mailerEntities();

            ObservableCollection<Contact> filteredContacts = new ObservableCollection<Contact>();

            string[] stateArray = (from s in states where s.IsChecked==true select s.State).ToArray();
            string[] countyArray= (from c in counties where c.IsChecked==true select c.County).ToArray();
            string[] genderArray= (from g in genders where g.IsChecked==true select g.Gender).ToArray();
            string[] industryArray = (from i in industries where i.IsChecked==true select i.Industry).ToArray();
            string[] contactedArray = (from c in contacted where c.IsChecked==true select c.IsContacted.ToString()).ToArray();
            string[] sicCodeArray = (from c in codes where c.IsChecked==true select c.SicCodeDescription).ToArray();

            var contacts=(from c in db.Contacts
                          where
                          stateArray.Contains(c.State) &&
                          countyArray.Contains(c.County) &&
                          genderArray.Contains(c.Gender) &&
                          industryArray.Contains(c.Industry) &&
                          contactedArray.Contains(c.IsContacted) &&
                          sicCodeArray.Contains(c.SIC_Code_Description)

                          select c).ToList();

            foreach (Contact contact in contacts)
            {
                if(hasWebsite==true)
                {
                    if(!String.IsNullOrEmpty(contact.WebSite))
                    {
                        filteredContacts.Add(contact);
                    }
                }
                else
                {
                    filteredContacts.Add(contact);
                }

            }

            return filteredContacts;
        }

        public void AddContactsRange(ObservableCollection<Contact> contacts)
        {

                db.Contacts.AddRange(contacts);
                db.SaveChanges();

        }

        public void ResetFilters()
        {
            ResetStates();
            ResetCounties();
            ResetIsContactedFilters();
            ResetGenders();
            ResetIndustries();
            ResetSicFilters(); 

        }

        private void ResetStates()
        {
            db.Database.ExecuteSqlCommand("TRUNCATE TABLE [StateFilter]");

            db = new digital_datahouse_bulk_mailerEntities();

            List<StateFilter> stateFilters = new List<StateFilter>();

            var states = (
                from c in db.Contacts
                select c.State

                ).Distinct().ToList();

            foreach (var stateName in states)
            {
                StateFilter state = new StateFilter();
                state.State = stateName;
                state.IsChecked = true;
                stateFilters.Add(state);

            }


            db.StateFilters.AddRange(stateFilters);
            db.SaveChanges();

        }

        public void DeleteAllContacts()
        {
            db.Database.ExecuteSqlCommand("TRUNCATE TABLE [Contact]");           
            db = new digital_datahouse_bulk_mailerEntities();   
        }

        private void ResetCounties()
        {
            db.Database.ExecuteSqlCommand("TRUNCATE TABLE [CountyFilter]");
            db = new digital_datahouse_bulk_mailerEntities();

            List<CountyFilter> countyFilters = new List<CountyFilter>();

            var counties = (
                from c in db.Contacts
                select c.County

                ).Distinct().ToList();

            foreach (var countyName in counties)
            {
                CountyFilter county = new CountyFilter();
                county.County = countyName;
                county.IsChecked = true;
                countyFilters.Add(county);
            }

            db.CountyFilters.AddRange(countyFilters);
            db.SaveChanges();
        }

        private void ResetGenders()
        {
            db.Database.ExecuteSqlCommand("TRUNCATE TABLE [GenderFilter]");
            db = new digital_datahouse_bulk_mailerEntities();

            List<GenderFilter> genderFilters = new List<GenderFilter>();

            var genders = (
                from c in db.Contacts
                select c.Gender

                ).Distinct().ToList();

            foreach (var genderName in genders)
            {
                GenderFilter gender = new GenderFilter();
                gender.Gender = genderName;
                gender.IsChecked = true;
                genderFilters.Add(gender);
            }

            db.GenderFilters.AddRange(genderFilters);
            db.SaveChanges();
        }

        private void ResetIndustries()
        {
            db.Database.ExecuteSqlCommand("TRUNCATE TABLE [IndustryFilter]");
            db = new digital_datahouse_bulk_mailerEntities();

            List<IndustryFilter> industryFilters = new List<IndustryFilter>();

            var industries = (
                from c in db.Contacts
                select c.Industry

                ).Distinct().ToList();

            foreach (var industryName in industries)
            {
                IndustryFilter industry = new IndustryFilter();
                industry.Industry = industryName;
                industry.IsChecked = true;
                industryFilters.Add(industry);
            }

            db.IndustryFilters.AddRange(industryFilters);
            db.SaveChanges();
        }

        private void ResetIsContactedFilters()
        {
            db.Database.ExecuteSqlCommand("TRUNCATE TABLE [IsContactedFilter]");
            db = new digital_datahouse_bulk_mailerEntities();

            List<IsContactedFilter> isContactedFilters = new List<IsContactedFilter>();

            var isContacted = (
                from c in db.Contacts
                select c.IsContacted

                ).Distinct().ToList();

            foreach (var contactedName in isContacted)
            {
                IsContactedFilter contacted = new IsContactedFilter();
                contacted.IsContacted = contactedName;
                contacted.IsChecked = true;
                isContactedFilters.Add(contacted);
            }

            db.IsContactedFilters.AddRange(isContactedFilters);
            db.SaveChanges();
        }

        private void ResetSicFilters()
        {
            db.Database.ExecuteSqlCommand("TRUNCATE TABLE [SicCodeDescriptionFilter]");
            db = new digital_datahouse_bulk_mailerEntities();

            List<SicCodeDescriptionFilter> sicFilters = new List<SicCodeDescriptionFilter>();

            var sics = (
                from c in db.Contacts
                select c.SIC_Code_Description

                ).Distinct().ToList();

            foreach (var sic in sics)
            {
                SicCodeDescriptionFilter sicCode = new SicCodeDescriptionFilter();
                sicCode.SicCodeDescription = sic;
                sicCode.IsChecked = true;
                sicFilters.Add(sicCode);
            }

            db.SicCodeDescriptionFilters.AddRange(sicFilters);
            db.SaveChanges();
        }

        public void UpdateIsContactedInformation(Contact contact)
        {
            db = new digital_datahouse_bulk_mailerEntities();

            contact.IsContacted = "True";
            contact.MessageDateSent = DateTime.Today;

            db.Contacts.AddOrUpdate(contact);
            db.SaveChanges();
        }
    }
}

This is the view that uses the ViewModel it is called ContactsView - this view is included in the MainWindow as other views are

ContactsView :

<UserControl x:Class="Digital_Data_House_Bulk_Mailer.View.ContactsView"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         xmlns:local="clr-namespace:Digital_Data_House_Bulk_Mailer.View"
         xmlns:Controls="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
         xmlns:model="clr-namespace:Digital_Data_House_Bulk_Mailer.ViewModel"
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300">
<UserControl.DataContext>
    <model:ContactsViewModel/>
</UserControl.DataContext>
<Grid Margin="0,0,-690,-36" >
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="61*"/>
        <ColumnDefinition Width="10*"/>
    </Grid.ColumnDefinitions>
    <Button  Style="{StaticResource AccentedSquareButtonStyle}" Command="{Binding DeleteCommand}" Controls:TextBoxHelper.ClearTextButton="True" x:Name="delete" Content="DELETE" HorizontalAlignment="Left" Margin="115,21,0,0" VerticalAlignment="Top"  Width="100" RenderTransformOrigin="0.267,0.519"/>
    <Button  Style="{StaticResource AccentedSquareButtonStyle}" Command="{Binding UpdateCommand}" Controls:TextBoxHelper.ClearTextButton="True" x:Name="update" Content="add / update" HorizontalAlignment="Left" Margin="10,21,0,0" VerticalAlignment="Top"  Width="100" RenderTransformOrigin="0.267,0.519"/>
    <Button  Style="{StaticResource AccentedSquareButtonStyle}"  Controls:TextBoxHelper.ClearTextButton="True" x:Name="bulk_import" Content="import new data" HorizontalAlignment="Left" Margin="220,21,0,0" VerticalAlignment="Top"  Width="110" RenderTransformOrigin="0.267,0.519" Click="bulk_import_Click"/>
    <DataGrid SelectedItem="{Binding Contact}" AutoGenerateColumns="True" ItemsSource="{Binding Path=Contacts, Mode=TwoWay}" Style="{StaticResource AzureDataGrid}"  x:Name="dataGridCodeBehind"  Margin="10,54,521,0" VerticalAlignment="Top"  HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch" ColumnWidth="*">
        <DataGrid.ColumnHeaderStyle>
            <Style TargetType="DataGridColumnHeader">
                <Setter Property="FontSize" Value="10"/>
            </Style>
        </DataGrid.ColumnHeaderStyle>
    </DataGrid>
    <Button IsEnabled="{Binding IsRefreshEnabled}" Style="{StaticResource AccentedSquareButtonStyle}" Command="{Binding LoadCommand}" x:Name="refreshData" Content="Refresh Contacts" HorizontalAlignment="Left" Height="22" Margin="335,21,0,0" VerticalAlignment="Top" Width="114"/>
    <Controls:ProgressRing IsActive="{Binding IsRefreshProgressActive}" Foreground="{DynamicResource AccentColorBrush}" Margin="720,0,0,0" RenderTransformOrigin="-2.889,0.463" HorizontalAlignment="Left" VerticalAlignment="Top" Height="50" Width="50"/>
    <Button x:Name="deleteContacts" Command="{Binding DeleteAllContactsCommand}" Style="{StaticResource AccentedSquareButtonStyle}" Content="Delete All Contacts" HorizontalAlignment="Left" Height="22" Margin="454,21,0,0" VerticalAlignment="Top" Width="114"/>
    <Button x:Name="recreateFilters" Command="{Binding RecreateFiltersCommand}" Content="Recreate TO MAIL Filters" HorizontalAlignment="Left" Style="{StaticResource AccentedSquareButtonStyle}" Height="22" Margin="573,21,0,0" VerticalAlignment="Top" Width="142"/>

</Grid>

The very bad thing is that when I try to debug it does not even go to the code - method call. Tried also to use some profiling tools but I did not come to any conclusion what is making this freeze issue...

When I run the query on the db from the db editor I get instant results .

I also use a SSRS report in the app displayed using ReportViewer - it also works fine and returns the same data - it is displayed on a separate View.

On one of the views I display a GIF animation using WpfAnimatedGif Library - I tried to remove this reference to see if that is making the issue but it does not the freeze goes on...

I also tried to rewrite my repository class to use using command for the creation of the new instance of db for every method but this is not what is making the issue.

Solution files: Google Disk Solution Link

Jovo Krneta
  • 548
  • 1
  • 14
  • 36
  • 2
    1. Why do you run an async method in a task (`Task.Run(() => _repository.GetContactsAsync())`)? 2. Why do you load *all* contacts? 3. The database size doesn't mean much, how many records are we talking about? Does it still freeze when you load less data? – Gert Arnold May 19 '18 at 21:41
  • A few days ago I was able to load 100 000 data with no any problem, now I tried to load 10 contacts and it will not freeze, when I load 1000 it freezes. I tried to remove async and await and it makes no difference - it freezes again.A also tried to remove all the styles from that view, still no difference. This may be a db issue, maybe the file is somehow corrupt. The strange thing is that I have a view where I fetch the same data and it loads fine... – Jovo Krneta May 19 '18 at 22:42
  • A also reduced the size of the local mdf file by running DBCC SHRINKDATABASE (0); GO , again the app freezes – Jovo Krneta May 19 '18 at 22:55
  • Hook up a profiler to your database and watch what is happening when you trigger the freeze. Nothing in your code stands out, but it definitely would be inefficient creating DbContexts then returning entities. I would recommend not returning Entities to your view, instead create a viewmodel, select your entities and populate viewmodels to return with just the data you need. With filtering, wherever possible, compose the conditions into your Linq rather than iterating over a list of entities. – Steve Py May 19 '18 at 23:26
  • @ Steve Py - since I am using local mdf file, I am not sure how to attach the sql server management studio profiler to monitor local mdf db file... – Jovo Krneta May 19 '18 at 23:39
  • I reconnected the app to Sql Server db and ran a profiler on a db, returns no sql statements after the app freezes. Application freezes no matter if it is using local db file or sql server... So this is not the issue here – Jovo Krneta May 20 '18 at 08:51
  • I think this has to to with incorrect async methods. As I said in my first comment the `Task.Run` pattern is weird. Also, `async void` is an anti pattern. At least return `Task`. Freezing while the database isn't even accessed indicates deadlocking threads. – Gert Arnold May 20 '18 at 09:33
  • I tried both things to return a task instead of void and also tried the second option of totally removing the async and await by making the calls synh, makes no changes. – Jovo Krneta May 20 '18 at 09:37
  • I included the solution folder zipped on Google disk with all the needed items to recreate the issue, go to Data Setup, click Import , first select the Alaska_short file for import by clicking select file, check both checkboxes , for separator choose comma, click load data for mapping, map at least the company name and email with GenericCompanyEmailAddress, click import, when done close the window for import and click Refresh button. It will be ok. Repeat the process with the Alaska_large.zip file and the app will freeze. – Jovo Krneta May 20 '18 at 10:39
  • The Contacts list is getting filled from the db, looks like this is not the issue, I also tried to recreate the entire partial ContactsView from scratch - the freeze is still on. – Jovo Krneta May 21 '18 at 10:57
  • When I limit the load to 50 Contacts it loads the data after 10 secunds, after I increase the number of records it freezes, I also tried to manually define only a few columns to display but the grid freezes again. This looks to be the grid rendering issue... – Jovo Krneta May 21 '18 at 12:42

2 Answers2

3

I finally solved this issue. What I needed is to add the Height="500" property to the data grid.

Removing the Height property makes the DataGrid freeze when displaying more than 50 rows in my case. With the added Height it loads 5000 records in less than a second.

Jovo Krneta
  • 548
  • 1
  • 14
  • 36
0

Just a suggestion.

I was working with grid with large lists. I would suggest you turn on the virtualization and that can make some more improvements to the performance of the UI.

you can refer this link for more information

https://learn.microsoft.com/en-us/dotnet/framework/wpf/getting-started/whats-new#new-features-for-the-virtualizingpanel

karmjit singh
  • 229
  • 3
  • 14