title: Lifeupdate DataGrid from TextFile with good performance
body: <p><strong>Actual state:</strong></p>
  
  <p>I have a <code>DataGrid</code> with 4 Columns (Icon|DateTime|LogLevel|Message)</p>
  
  <p>I use it as a viewer to present entries of a <code>LogFile</code>.
  When opening the <code>Window</code> the UI lags and alot of entries are added one by one to the <code>DataGrid</code>.</p>
  
  <p><strong>Note:</strong> I am already using multiple threads. My UI-Thread is not freezing. Its just taking way to long to fill the whole <code>DataGrid</code>.</p>
  
  <p><strong>What I want:</strong></p>
  
  <p>I would prefer something like "pre-render" the whole window before showing it to the user.</p>
  
  <p>When I have aready opened the <code>Window</code> once - every time I open it again, its no problem anymore.(not rendering new .... ?)</p>
  
  <p><strong>What I have tried:</strong></p>
  
  <ul>
  <li>Setting the <code>Visibility</code> to <code>Hidden</code> and wait(<code>Thread.Sleep()</code>) 10 secs then set <code>Visibility = Visibility.Visible</code>;</li>
  <li>Adding all the Data into my <code>DataGrid</code> in ViewModel-Constructor</li>
  </ul>
  
  <p>but all this didn't really fix it. I ain't even sure if it's the C# Code or just the Bindings...</p>
  
  <p>This may be a silly question but is there a way to "pre-render" the <code>DataGrid</code> and its <code>Content</code> before displaying it ?</p>
  
  <p><strong>EDIT:</strong></p>
  
  <p>I also use some <code>DataTriggers</code> to set RowColor but this might not be the problem..</p>
  
  <p><strong>Here is some Code I use:</strong></p>
  
  <blockquote>
    <p>The Entry Class:</p>
  </blockquote>
  
  <pre><code> public class LogEntry
  {
      public string LogLevel { get; set; }
      public string LogLevelIcon
      {
          get
          {
              switch(LogLevel)
              {
                  case "[D]":     //IF DEBUG ENTRY:
                      return "pack://application:,,,/Resources/Bug.png";
                  case "[F]":     //IF FATAL ENTRY
                      return "pack://application:,,,/Resources/System-error-alt.png";
                  case "[E]":     //IF ERROR ENTRY
                      return "pack://application:,,,/Resources/Error_32_WhiteBackground.png";
                  case "[I]":     //IF INFO ENTRY
                      return "pack://application:,,,/Resources/Info_32.png";
                  case "[W]":     //IF WARNING ENTRY
                      return "pack://application:,,,/Resources/Warning_32_WhiteBackground.png";
                  case "[DB]":    //IF DB ENTRY
                      return "pack://application:,,,/Resources/Database.png";
                  default:
                      return string.Empty;
              }                
          }
      }
      public string Message { get; set; }
      public DateTime DateTime { get; set; }
  
      public override string ToString()
      {
          return $"{LogLevel};{DateTime.ToString("dd.MM.yyyy HH:mm:ss")};{Message}";
      }
  }
  </code></pre>
  
  <blockquote>
    <p>Getting the Data from my LogFile:</p>
  </blockquote>
  
  <pre><code>public void ExtractDataFromLogFile(string logFilePath)
      {
          new Thread(() =&gt; {
  
              List&lt;string&gt; linesInFile = new List&lt;string&gt;();
              using (FileStream stream = File.Open(logFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
              {
                  using (StreamReader reader = new StreamReader(stream))
                  {
                      while (true)
                      {
                          while (!reader.EndOfStream)
                          {
                              ProcessFileContent(reader.ReadLine());
                          }
                          while (reader.EndOfStream)
                          {
                              Thread.Sleep(50);
                          }
                      }
                  }
              }
  
          }).Start();
      }
  </code></pre>
  
  <blockquote>
    <p>Adding to the <code>ObservableCollection&lt;LogEntry&gt;() _logEntries;</code>:</p>
  </blockquote>
  
  <pre><code>private void ProcessFileContent(string line)
      {
          Match match = _regex.Match(line);
          if (match.Success)
          {
              LogEntry entry = new LogEntry()
              {
                  LogLevel = match.Groups[1].ToString(),
                  DateTime = DateTime.Parse(match.Groups[2].ToString(), new CultureInfo("de-DE")),
                  Message = match.Groups[3].ToString()
              };                    
              _logEntries.Add(entry);                    
          }
      }
  </code></pre>
  
  <blockquote>
    <p>Finally the XAML of the DataGrid (Styles left out!):</p>
  </blockquote>
  
  <pre><code>&lt;DataGrid Grid.Row="1"
            x:Name="DataGrid"
            Grid.ColumnSpan="2"
            Margin="5"
            IsReadOnly="True"
            AutoGenerateColumns="False"
            CanUserReorderColumns="False"
            ItemsSource="{Binding Path=ItemsView, UpdateSourceTrigger=PropertyChanged}"&gt;
    &lt;DataGrid.Columns&gt;
              &lt;DataGridTemplateColumn Width="Auto"&gt;
                  &lt;DataGridTemplateColumn.CellTemplate&gt;
                      &lt;DataTemplate&gt;
                          &lt;Image Source="{Binding Path=LogLevelIcon, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
                                 Width="16" 
                                 Height="16"&gt;&lt;/Image&gt;
                      &lt;/DataTemplate&gt;
                  &lt;/DataGridTemplateColumn.CellTemplate&gt;
              &lt;/DataGridTemplateColumn&gt;
              &lt;DataGridTextColumn Width="Auto" Header="Datum"
                                  Binding="{Binding Path=DateTime, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"/&gt;               
              &lt;DataGridTextColumn Width="*" Header="Meldung"
                                  Binding="{Binding Path=Message, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"/&gt;
          &lt;/DataGrid.Columns&gt;
      &lt;/DataGrid&gt;
  </code></pre>
  
  <p>Note that "ItemsView" is typeof <code>ICollectionView</code></p>
  
  <p>I fill it here:</p>
  
  <pre><code>private void InitializeCollection()
      {
          ItemsView = CollectionViewSource.GetDefaultView(_logEntries);
          BindingOperations.EnableCollectionSynchronization(_logEntries, _lock);
      }
  </code></pre>