- Home
- Forum
- Xamarin.Forms
- Binding Dynamic Columns Without AutoGenerate Columns
Binding Dynamic Columns Without AutoGenerate Columns
I have dataset with dynamic number of columns. I am using a DataTable to create the data. I have created an object called TableCellViewModel that contains the data I want for each cell. The table that gets rendered puts a checkbox in every cell. In the checkbox checked handler I get the binding context of the checkbox that raised the even. The binding context is the entire row. What am I missing? All of your examples binding to a data table show binding to strings.
SfDataGrid dataGrid = new SfDataGrid();
dataGrid.GridLoaded += DataGrid_GridLoaded;
dataGrid.QueryRowHeight += DataGrid_QueryRowHeight;
dataGrid.AutoGenerateColumns = false;
dataGrid.Style = Content.FindByName("GridStyle") as Style;
dataGrid.VerticalOverScrollMode = VerticalOverScrollMode.None;
dataGrid.ItemsSource = tableViewModel.Data;
int columnNumber = 0;
foreach (KeyValuePair<string, TableColumnWidthType> kvp in tableViewModel.Columns)
{
GridTemplateColumn gridTemplate = new GridTemplateColumn();
gridTemplate.MappingName = $"[{columnNumber}]"; <-- I'm guessing this is the problem
gridTemplate.HeaderText = string.IsNullOrWhiteSpace(kvp.Key) ? string.Empty : kvp.Key;
gridTemplate.HeaderFontAttribute = FontAttributes.Bold;
gridTemplate.HeaderTextAlignment = TextAlignment.Center;
gridTemplate.HeaderFont = "SourceSansPro-Bold.ttf#Source Sans Pro";
gridTemplate.HeaderCellTextSize = 14;
gridTemplate.CellTemplate = (DataTemplate)Content.FindByName("CellTemplate");
gridTemplate.LineBreakMode = LineBreakMode.CharacterWrap;
if (kvp.Value == TableColumnWidthType.Header)
{
gridTemplate.ColumnSizer = ColumnSizer.SizeToHeader;
}
else
{
gridTemplate.Width = 200;
}
dataGrid.Columns.Add(gridTemplate);
columnNumber++;
}
Here is the cell template. I want to either show a label or a checkbox. Every cell shows a checkbox, which makes sense if the template is binding to the entire row.
<DataTemplate x:Key="CellTemplate" x:Name="CellTemplate">
<Grid Margin="1,1,1,0" BackgroundColor="{ DynamicResource DataGridBackgroundColor }">
<Label Grid.Row="0" Grid.Column="0"
Text="{Binding CellText}"
IsVisible="{Binding CellType, Converter={StaticResource TextCellVisibility}}"
IsEnabled="{Binding CanEdit}"
Margin="3,0,0,0"
TextColor="{ DynamicResource DataGridCellTextColor }"
VerticalOptions="Center"
HorizontalOptions="Start">
<Label.GestureRecognizers>
<TapGestureRecognizer Tapped="CellText_Tapped"/>
</Label.GestureRecognizers>
</Label>
<CheckBox Grid.Row="0" Grid.Column="0"
IsChecked="{Binding CheckboxValue}"
IsVisible="{Binding CellType, Converter={StaticResource CheckBoxCellVisibility}}"
IsEnabled="{Binding CanEdit}"
CheckedChanged="CellCheckBox_Checked"
Color="{ DynamicResource DataGridCellTextColor }"
HorizontalOptions="Center" />
</Grid>
</DataTemplate>
SIGN IN To post a reply.
10 Replies
1 reply marked as answer
KK
Karthikraja Kalaimani
Syncfusion Team
July 20, 2020 12:55 PM UTC
Hi Nick,
Currently, we are validating your requirement. We will update further details on or before 22nd July 2020. We appreciate your patience until then.
Regards,
Karthik Raja
Currently, we are validating your requirement. We will update further details on or before 22nd July 2020. We appreciate your patience until then.
Regards,
Karthik Raja
KK
Karthikraja Kalaimani
Syncfusion Team
July 22, 2020 09:44 AM UTC
Hi Nick,
The data model values are in Array type in DataTable, so you can directly bind the array in the elements like below highlighted code snippet.
Code snippet :
The data model values are in Array type in DataTable, so you can directly bind the array in the elements like below highlighted code snippet.
Code snippet :
|
[XAML]
<ContentPage.Resources> <ResourceDictionary>
<DataTemplate x:Key="CellTemplate" x:Name="CellTemplate">
<Grid Margin="1,1,1,0" >
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"></ColumnDefinition>
<ColumnDefinition Width="100"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0"
Text="{Binding [1]}"
Margin="3,0,0,0"
VerticalOptions="Center"
HorizontalOptions="Start">
<Label.GestureRecognizers>
<TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped"/>
</Label.GestureRecognizers>
</Label>
<CheckBox Grid.Row="0" Grid.Column="1"
IsChecked="{Binding [2]}"
CheckedChanged="CheckBox_CheckedChanged"
HorizontalOptions="Center" />
</Grid>
</DataTemplate>
</ResourceDictionary>
</ContentPage.Resources>
[.CS] SfDataGrid dataGrid = new SfDataGrid(); dataGrid.AutoGenerateColumns = false;
dataGrid.VerticalOverScrollMode = VerticalOverScrollMode.None;
dataGrid.ItemsSource = viewModel.Data;
dataGrid.ColumnSizer = ColumnSizer.Auto;
int columnNumber = 0;
for(int i=0;i<2;i++)
{
GridTemplateColumn gridTemplate = new GridTemplateColumn();
gridTemplate.MappingName = $"[{columnNumber}]";
gridTemplate.HeaderText = viewModel.Data.Columns[columnNumber].ColumnName; gridTemplate.HeaderFontAttribute = FontAttributes.Bold;
gridTemplate.HeaderTextAlignment = TextAlignment.Center;
gridTemplate.HeaderCellTextSize = 14;
gridTemplate.BindingContextChanged += GridTemplate_BindingContextChanged;
gridTemplate.CellTemplate = (DataTemplate)Content.FindByName("CellTemplate");
gridTemplate.LineBreakMode = LineBreakMode.CharacterWrap;
dataGrid.Columns.Add(gridTemplate);
columnNumber++;
}
this.stack.Children.Add(dataGrid); |
Sample link : https://www.syncfusion.com/downloads/support/directtrac/general/ze/DataGridSample1373350445-244950774.zip
Regards,
Karthik Raja
NI
Nick
July 22, 2020 02:18 PM UTC
I want the data in column 1 of the DataTable to be the binding context for column 1 of the SFDataGrid. I want the data in column 2 of the DataTable to be the binding context for column 2 of the SFDataGrid. Since I have an unknown number of columns I can't just create templates for each column.
Each cell of the DataTable contains the same object type, and each cell in the SFDataGrid will contain either a Checkbox or a label.
KK
Karthikraja Kalaimani
Syncfusion Team
July 23, 2020 12:06 PM UTC
Hi Nick.
You need to create each cell template for each column to achieve your requirement in Code behind like the below high-lighted code snippet. For more details please refer to the below code snippet.
Code snippet :
You need to create each cell template for each column to achieve your requirement in Code behind like the below high-lighted code snippet. For more details please refer to the below code snippet.
Code snippet :
|
SfDataGrid dataGrid = new SfDataGrid();
dataGrid.AutoGenerateColumns = false;
dataGrid.VerticalOverScrollMode = VerticalOverScrollMode.None;
dataGrid.ItemsSource = viewModel.Data;
dataGrid.ColumnSizer = ColumnSizer.Auto;
int columnNumber = 0;
for(int i=0;i<2;i++)
{
GridTemplateColumn gridTemplate = new GridTemplateColumn();
gridTemplate.MappingName = $"[{columnNumber}]";
gridTemplate.HeaderText = viewModel.Data.Columns[columnNumber].ColumnName;
gridTemplate.HeaderFontAttribute = FontAttributes.Bold;
gridTemplate.HeaderTextAlignment = TextAlignment.Center;
gridTemplate.HeaderCellTextSize = 14;
gridTemplate.CellTemplate = GetTemplate(i);
gridTemplate.LineBreakMode = LineBreakMode.CharacterWrap;
dataGrid.Columns.Add(gridTemplate);
columnNumber++;
}
this.stack.Children.Add(dataGrid);
}
private DataTemplate GetTemplate(int index)
{
DataTemplate cellTemplate = new DataTemplate(() =>
{
Label label;
label = new Label();
label.SetBinding(Label.TextProperty, new Binding($"[{index}]"));
return label;
});
return cellTemplate;
} |
Sample link : https://www.syncfusion.com/downloads/support/directtrac/general/ze/DataGridSample1373350445-95908066.zip
Please let us know if you need any further assistance from this.
Regards,
Karthik Raja
Marked as answer
NI
Nick
July 24, 2020 03:54 AM UTC
This seems to be working. I'm running into an issue in my QueryRowHeight event handler now. It is throwing an out of range exception if there is more than one table on a page. The handler is pretty simple. The exception is happening in the GetRowHeight call.
SfDataGrid dataGrid = sender as SfDataGrid;
if (e.RowIndex > 0)
{
e.Height = SfDataGridHelpers.GetRowHeight(dataGrid, e.RowIndex);
e.Handled = true;
}
I'm also seeing odd behavior on the checkboxes. When the table loads the CheckedChanged event is firing. Any idea why that would be?
KK
Karthikraja Kalaimani
Syncfusion Team
July 27, 2020 08:07 AM UTC
Hi Nick,
We have checked the reported issue “Out Range expection thrown when call GetRowHeight method” with more than one SfDatGrid. The GetRowHeight method working fine as expected without exception. We have attached the tested sample for your reference.
Sample link : https://www.syncfusion.com/downloads/support/directtrac/general/ze/DataGridSample2062071549.zip
Please check the sample and let us know if you still facing the same issue? If not, please modify the sample based on your scenario and revert us back.
We have checked the reported issue “Out Range expection thrown when call GetRowHeight method” with more than one SfDatGrid. The GetRowHeight method working fine as expected without exception. We have attached the tested sample for your reference.
Sample link : https://www.syncfusion.com/downloads/support/directtrac/general/ze/DataGridSample2062071549.zip
Please check the sample and let us know if you still facing the same issue? If not, please modify the sample based on your scenario and revert us back.
Regarding “odd behavior on the CheckBox”
We have checked with single row with IsChecked value as true and we saw that the CheckedChanged event is fired continuously with value as true and false. So, could you please confirm whether or not are you facing the same behavior on your side?. If not, please provide a code to check the behavior of CheckedChanged event. It will help us to give better solution earlier.
Regards,
Karthik Raja
NI
Nick
July 31, 2020 03:29 AM UTC
I am seeing the CheckChanged event handler getting fired with both true and false as well. It doesn't seem to match anything in the view model.
KK
Karthikraja Kalaimani
Syncfusion Team
August 3, 2020 01:26 PM UTC
Hi Nick,
We have checked the behavior of CheckedChanged event. In our source we create content and dispose of for the DataTemplate in two places which is used to calculate the height and width of the element. So, only it triggers more than 4 times for a cell.
Regards,
Karthik Raja
We have checked the behavior of CheckedChanged event. In our source we create content and dispose of for the DataTemplate in two places which is used to calculate the height and width of the element. So, only it triggers more than 4 times for a cell.
Regards,
Karthik Raja
NI
Nick
August 7, 2020 03:13 AM UTC
I don't understand what you're saying here.
KK
Karthikraja Kalaimani
Syncfusion Team
August 10, 2020 01:19 PM UTC
Hi Nick,
In our source, we create a view for the DataTemplate by using Xamarin forms method DataTemplate.CreateContent() and dispose of the view by setting the null value to the view. So, the CheckedChanged event gets triggered with true value and false value after that method call and the view set to null. We are doing these operations in two places while measuring the height and width of GridTemplateColumn.
Regards,
Karthik Raja
In our source, we create a view for the DataTemplate by using Xamarin forms method DataTemplate.CreateContent() and dispose of the view by setting the null value to the view. So, the CheckedChanged event gets triggered with true value and false value after that method call and the view set to null. We are doing these operations in two places while measuring the height and width of GridTemplateColumn.
Regards,
Karthik Raja
SIGN IN To post a reply.