0
votes

I want to bind some data to columns created dynamically in my code behind. It's working with DataGridTextColumn but not with DataGridTemplateColumn.

Since DataGridTemplateColumn doesn't have a "Binding" property, I created a custom column deriving from DataGridTemplateColumn as some solutions suggested. However the SetBinding throw a System.Exception when GenerateElement method is called and crashes the program.

class DataGridBoundColumn : DataGridTemplateColumn
{
    public BindingBase Binding { get; set; }

protected override FrameworkElement GenerateEditingElement(DataGridCell cell, object dataItem)
{
    var element = base.GenerateEditingElement(cell, dataItem);
    if (element != null && Binding != null)
        element.SetBinding(ContentPresenter.ContentProperty, Binding);
    return element;
}

protected override FrameworkElement GenerateElement(DataGridCell cell, object dataItem)
{
    var element = base.GenerateElement(cell, dataItem);
    if (element != null && Binding != null)
        element.SetBinding(ContentPresenter.ContentProperty, Binding);//Error is here
    return element;
}
}

The code used to create columns and to populate the grid:

dataGrid.Columns.Add(new Models.DataGridBoundColumn
{
    Header = " Week" + week.WeekNumber,
    Binding = new Binding { Path = new PropertyPath("[" + i.ToString() + "]") },
    CellTemplate = (DataTemplate)Resources["templateCell"]
});

var collection = new ObservableCollection<object>();
List<string> list = new List<string>(new string[] { "2", "3", "7" });
for (int i= 0; i < list.Count; i++)//Trying with some test data
{
    collection.Add(list);
}
dataGrid.ItemsSource = collection;

The DataTemplate I'm using for testing at he moment:

<DataTemplate x:Key="templateCell">
    <StackPanel>
        <TextBlock Text="{Binding WeekNumber}" />
        <Rectangle HorizontalAlignment="Left" Height="18" Width="20" Fill="{Binding ItemColor}" />
    </StackPanel>
</DataTemplate>

I have looked closely at the binding class documentation, but I have still no clue why it's throwing this exception...

The error is :

Catastrophic failure (Exception from HRESULT: 0x8000FFFF (E_UNEXPECTED))

at Windows.UI.Xaml.FrameworkElement.SetBinding(DependencyProperty dp, BindingBase binding) at Application.Models.DataGridBoundColumn.GenerateElement(DataGridCell cell, Object dataItem) in C:...\Models\DataGridBoundColumn.cs:line 26 at Microsoft.Toolkit.Uwp.UI.Controls.DataGrid.PopulateCellContent(Boolean isCellEdited, DataGridColumn dataGridColumn, DataGridRow dataGridRow, DataGridCell dataGridCell) at Microsoft.Toolkit.Uwp.UI.Controls.DataGrid.AddNewCellPrivate(DataGridRow row, DataGridColumn column) at Microsoft.Toolkit.Uwp.UI.Controls.DataGrid.CompleteCellsCollection(DataGridRow dataGridRow) at Microsoft.Toolkit.Uwp.UI.Controls.DataGrid.GenerateRow(Int32 rowIndex, Int32 slot, Object dataContext) at Microsoft.Toolkit.Uwp.UI.Controls.DataGrid.AddSlots(Int32 totalSlots) at Microsoft.Toolkit.Uwp.UI.Controls.DataGrid.RefreshRows(Boolean recycleRows, Boolean clearRows) at Microsoft.Toolkit.Uwp.UI.Controls.DataGrid.RefreshRowsAndColumns(Boolean clearRows) at Microsoft.Toolkit.Uwp.UI.Controls.DataGrid.MeasureOverride(Size availableSize)

1
Can you please include the full exception message?Corentin Pane
Just added the complete stacktracePierre mrq
Thanks. I replaced "Défaillance irrémédiable" with "Catastrophic failure" as I believe it is the correct english translation, please re-edit otherwise!Corentin Pane
Does this answer your question? Catastrophic failure in xaml bindingCorentin Pane
Saw it earlier, I don't think it's the same issuePierre mrq

1 Answers

0
votes

Ok so it's working correctly now and it was an easy fix. The issue was the incorrect usage of Contentproperty, since my StackPanel (in DataTemplate) doesn't have one it's getting this error. The correct property is DataContextProperty.

  class DataGridBoundColumn : DataGridTemplateColumn
   {
     public BindingBase Binding { get; set; }
    
     protected override FrameworkElement GenerateEditingElement(DataGridCell cell, object dataItem)
     {
       var element = base.GenerateEditingElement(cell, dataItem);
       if (element != null && Binding != null)
         element.SetBinding(ContentPresenter.DataContextProperty, Binding);
       return element;
     }
    
     protected override FrameworkElement GenerateElement(DataGridCell cell, object dataItem)
     {
       var element = base.GenerateElement(cell, dataItem);
       if (element != null && Binding != null)
         element.SetBinding(ContentPresenter.DataContextProperty, Binding);
       return element;
     }
   }

Thanks to @PeterFleischer-3316 from Microsoft Q&A for solving the issue.