title: Performance of WPF datagrid when using DataGridTemplateColumn
body: <p>I am using <code>DataGrid</code> to show storagehouse occupancy (Occupied-Show Image With a box, Not Occupied-Show Empty Image).<br>
  In DataGrid I am using <code>DataGridTemplateColumn</code> to override the Images.
  My Main Form XAML Code: </p>
  
  <pre><code>&lt;xctk:BusyIndicator Name="ctrlBusy" IsBusy="False" BusyContent="Generating Maps..." &gt;
  &lt;Grid&gt;
      &lt;StackPanel&gt;
          &lt;Button Name="btnClick" Grid.Row="0" Click="Button_Click_1" Height="44" VerticalAlignment="Top" 
          HorizontalAlignment="Left" Width="114" Panel.ZIndex="4" Margin="6,3,0,0"&gt;Click&lt;/Button&gt;
  
          &lt;StackPanel Orientation="Vertical" Grid.Row="1"&gt;
              &lt;TextBlock  Background="SkyBlue" Height="50"&gt;
  
              &lt;/TextBlock&gt;
              &lt;DataGrid GridLinesVisibility="None" Background="SkyBlue" 
            BorderBrush="Transparent" IsReadOnly="True" ItemsSource="{Binding}" 
            AutoGenerateColumns="True" AutoGeneratingColumn="dgvMap_AutoGeneratingColumn"   
            CanUserAddRows="False" CanUserSortColumns="true" CanUserDeleteRows="False"  
            HeadersVisibility="Row" Name="dgvMap" SelectionMode="Single" 
            Panel.ZIndex="0" Margin="0,0,0,0" VirtualizingStackPanel.VirtualizationMode="Standard"&gt;
                  &lt;!--for removing the blue color bkground default for row selection--&gt;
                  &lt;DataGrid.Resources&gt;
                      &lt;SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" 
             Color="Transparent"/&gt;
                  &lt;/DataGrid.Resources&gt;
              &lt;/DataGrid&gt;
              &lt;TextBlock  Background="SkyBlue" Height="50"&gt;
  
              &lt;/TextBlock&gt;
          &lt;/StackPanel&gt;
      &lt;/StackPanel&gt;
  &lt;/Grid&gt;
  </code></pre>
  
  <p><br>
  Datatemplate for DataGrid:   </p>
  
  <pre><code>&lt;DataTemplate x:Key="MyDataTemplate" DataType="DataRowView"&gt;
      &lt;Grid Background="Transparent"&gt;
          &lt;Image Tag="{Binding}" Name="Layer0" Margin="0,0,0,0"  Panel.ZIndex="1"  
                 Width="50" Height="50"   ToolTipService.HasDropShadow="True" ToolTipService.ShowDuration="20000" ToolTipService.InitialShowDelay="200" &gt;
              &lt;Image.ToolTip&gt;
                  &lt;StackPanel&gt;
                      &lt;Label FontWeight="Bold" Background="Blue" Foreground="White" Content="{Binding}" /&gt;
                      &lt;TextBlock Padding="10" TextWrapping="WrapWithOverflow" Width="200"&gt;
                          This coil is located in this location. Yard Name is FG. Zone is Dispatch Area.
                      &lt;/TextBlock&gt;
                      &lt;Line Stroke="Black" StrokeThickness="1" X2="200" /&gt;
                      &lt;StackPanel Orientation="Horizontal"&gt;
                          &lt;Label FontWeight="Bold"&gt;Report to admin in case of coil location mismatch&lt;/Label&gt;
                      &lt;/StackPanel&gt;
                  &lt;/StackPanel&gt;
              &lt;/Image.ToolTip&gt;
              &lt;Image.Resources&gt;
                  &lt;Style TargetType="{x:Type Image}"&gt;
                      &lt;Setter Property="Source" Value="{Binding Converter={StaticResource IntToImageConverter}, ConverterParameter = Layer0}" /&gt;
                      &lt;Style.Triggers&gt;
                          &lt;Trigger Property="IsMouseOver" Value="True"&gt;
                              &lt;!-- Hover image --&gt;
                              &lt;Setter Property="Cursor" Value="Hand"/&gt;
                              &lt;Setter Property="Source" Value="C:\Users\Coil3.png"/&gt;
                              &lt;!--&lt;Setter Property="Source" Value="{Binding  Converter={StaticResource HoverImage}}"/&gt;--&gt;
                          &lt;/Trigger&gt;
                      &lt;/Style.Triggers&gt;
                  &lt;/Style&gt;
              &lt;/Image.Resources&gt;
          &lt;/Image&gt;
      &lt;/Grid&gt;
  &lt;/DataTemplate&gt;  
  </code></pre>
  
  <p><strong>Main Form Code-Behind:</strong>    </p>
  
  <pre><code>   private void Button_Click_1(object sender, RoutedEventArgs e)
      {
          btnClick.Content = "Data Loaded";
          Stopwatch sw = new Stopwatch();
          DataTable dt = dbLayer.tblSaddleSelectAll();
          sw.Start();
          dgvMap.ItemsSource = dt.DefaultView;
          sw.Stop();
          btnClick.Content = sw.ElapsedMilliseconds.ToString();
  
      }
  
  
  
    private void dgvMap_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
      {
          if (e.PropertyName == "row")
          {
              e.Column.Visibility = System.Windows.Visibility.Hidden;
          }
          var column = new DataRowColumn(e.PropertyName);
          column.Header = e.Column.Header;
          column.CellTemplate = (DataTemplate)Resources["MyDataTemplate"];
  
          e.Column = column;
      }  
  </code></pre>
  
  <p><strong>ValueConverter for DataGrid:</strong>   </p>
  
  <pre><code>public class BoolToImageConverter : IValueConverter
  {
  
      public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
      {
          ImageSource result = null;
          var intValue = value.ToString();
          switch (parameter.ToString())
          {
              case "Layer1":
                  if (intValue.ToUpper().Contains("EMPTY"))
                  {
                      result = null;
                  }
                  else
                  {
                      result = new BitmapImage(new Uri(@"C:\Users\Images\Box3.png"));
                  }
                  return result;
              default:
                  if (intValue.ToUpper().Contains("EMPTY"))
                  {
                      //result = null;
                      result = new BitmapImage(new Uri(@"C:\Users\Images\Box1.png"));
                  }
                  else
                  {
  
                      result = new BitmapImage(new Uri(@"C:\Users\Images\Box2.png"));
                  }
                  return result;
          }
  
      }
  
      public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
      {
          throw new NotImplementedException();
      }
  }  
  </code></pre>
  
  <p><strong>Custom DatagridTemplateColumn:</strong>   </p>
  
  <pre><code>public class DataRowColumn : DataGridTemplateColumn
  {
      public DataRowColumn(string column) { ColumnName = column; }
      public string ColumnName { get; private set; }
      protected override FrameworkElement GenerateElement(DataGridCell cell, object dataItem)
      {
          var row = (DataRowView)dataItem;
          var item = row[ColumnName];
          cell.DataContext = item;
          var element = base.GenerateElement(cell, item);
          return element;
      }
  }
  </code></pre>
  
  <p><strong>The Data from Database will be like this:</strong><br>
  <img src="https://i.stack.imgur.com/3e1lj.png" alt="enter image description here"></p>
  
  <p>I will be loading maximum of 250 columns,20 rows from database.<br>
  My Questions are:<br>
  1. The stopwatch i kept for checking time taken to load DataGrid. It is showing value less than 250ms. But in reality it is taking too much take show and for 4-6 second the UI gets hanged. Why is hanging? How to overcome it?<br>
  2. Is attaching DataTable's DefaultView to DataGrid is better way to do in performance in wise??<br>
  3. Is datagrid is best way to show map kind of layouts for the data given range? I need to show presence and absence with some tooltip descriptions.<br>
  4. Is there anything(properties) I missed in DataGrid to improve the performance.</p>