Binding every single cell with different DataTemplate in SfDataGrid
Hello
I need to set the DataTemplate (TextBox, ComboBox, DateTimePicker, ecc..) in every single cell of a SfDataGrid.
The DataGrid is initialized without columns. Columns are added at runtime programmatically.
The number of columns is unknow in design time.
The data value (and data type) shown in each cell is unknow at design time.
Cells of a single column have different data type.
PropertyRows is a collection of ExpandoObject: ObservableCollection<IDictionary<string, object>> PropertiesRows.
eHeader is a ExpandoObject: IDictionary<string, object> eHeaders
MyLeaf is a class of my project, MyLeaf.Value returns a object
This is my code:
WPF of a user control:
<syncfusion:SfDataGrid Name="grid"
ItemsSource="{Binding PropertiesRows, RelativeSource={RelativeSource AncestorType=UserControl}}"
AllowEditing="True" >
</syncfusion:SfDataGrid>
Code Behind:
private void addHeaders()
{
this.grid.Columns.Clear();
this.grid.Columns.Add(new GridTextColumn() { HeaderText = "Property", MappingName = "Property" });
foreach (var item in eHeaders)
{
var HeaderLeaf = item.Value as MyLeaf;
var headerText = HeaderLeaf.GetLeaf("Value").Value.ToString();
var mappingName = HeaderLeaf.GetLeaf("Value").Value.ToString();
var column = new GridTextColumn() { HeaderText = headerText, MappingName = mappingName };
column.CellTemplateSelector = CellSelector; //CellSelector is Initialized in the class contructor
this.grid.Columns.Add(column);
}
}
CellTemplateSelector : //Used for test some datatype
public class GridCellTemplateSelector : DataTemplateSelector
{
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
if (item != null)
{
var s = ((IDictionary<string, object>)item)["Property"];
switch (s)
{
case "Value":
DataTemplate c = Application.Current.Resources["textBlock"] as DataTemplate;
return c;
case "DisplayValue":
c = Application.Current.Resources["textBlock"] as DataTemplate;
return c;
case "Type":
c = Application.Current.Resources["combobox"] as DataTemplate;
return c;
case "Format":
c = Application.Current.Resources["textBlock"] as DataTemplate;
return c;
case "Visible":
c = Application.Current.Resources["checkbox"] as DataTemplate;
return c;
case "Position":
c = Application.Current.Resources["textBlock"] as DataTemplate;
return c;
}
return null;
}
return null;
}
}
App.xaml:
<Application.Resources>
<DataTemplate x:Key="textBlock">
<TextBlock />
</DataTemplate>
<DataTemplate x:Key="checkbox">
<CheckBox />
</DataTemplate>
<DataTemplate x:Key="combobox">
<ComboBox />
</DataTemplate>
</Application.Resources>
If i don't use the CellSelector, values are shown in the cells as text.
If i use the CellSelector, DateTemplate for each cell is setted correctly but values are not shown.
Thanks in advance
Michele
SIGN IN To post a reply.
3 Replies
SS
Susmitha Sundar
Syncfusion Team
September 3, 2019 11:00 AM UTC
Hi Michele,
Thank you for using Syncfusion controls.
Based on the provided information, we have checked your code snippet, you are using different DataTemplate with different controls. But you did not bind the values for that controls. Please refer the below code snippet,
Xaml:
|
<Window.Resources>
<local:CustomCellTemplateSelector x:Key="cellTemplateSelector"/>
<DataTemplate x:Key="DefaultTemplate">
<TextBlock Background="Wheat"
Foreground="Red"
Text="{Binding Path=EmployeeId}"
TextAlignment="Center" />
</DataTemplate>
<DataTemplate x:Key="AlternateTemplate">
<TextBlock Background="Beige"
Foreground="Green"
Text="{Binding Path=EmployeeId}"
TextAlignment="Center" />
</DataTemplate>
</Window.Resources> |
You have to bind the property for the DataTemplate controls. If you did not use the CellTemplate, SfDataGrid binds the property by default. If you manually add the CellTemplate controls, you need to bind the values for that controls.
Please refer the following user guide documentation links,
2. https://help.syncfusion.com/wpf/datagrid/column-types#reusing-same-datatemplate-for-multiple-columns
Please contact us for further assistance.
Regards,
Susmitha S
MI
Michele
September 6, 2019 10:21 AM UTC
Thanks for reply
You are right (my fault to copy/paste code) but my real problem was another one.
The solution, as you linked, was to read https://help.syncfusion.com/wpf/datagrid/column-types?&_ga=2.150673268.357777086.1567598411-681412903.1560935696#reusing-same-datatemplate-for-multiple-columns and using the DataContextHelper and SetCellBoundValue=true.
So, maybe i found the solution (i still have no tested it enough) but for now it works.
This set the correct DataTemplate to a single cell.
var column = new GridTextColumn() { HeaderText = headerText, MappingName = mappingName };
column.SetCellBoundValue = true;
column.CellTemplateSelector = CellSelector;
public class GridCellTemplateSelector : DataTemplateSelector
{
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
MyLeaf leaf;
if (item != null)
{
var u = (DataContextHelper)item;
var v = u.Value;
if (v.GetType() == typeof(MyLeaf))
{
leaf = (MyLeaf)v; //This is the value i needed to set the right template. It is a value of an ExpandoObject field where the field name is unknow
}
else
{
return null;
}
var type = leaf.Type.ToString();
switch (type)
{
case "String":
DataTemplate c = Application.Current.Resources["textBlock"] as DataTemplate;
return c;
<DataTemplate x:Key="textBlock" >
<TextBlock Text="{Binding Value.Value}" />
</DataTemplate>
I'm not sure if this is the right approach, it seems to work.
There is maybe a better solution?
Thanks
Michele
FP
Farjana Parveen Ayubb
Syncfusion Team
September 9, 2019 10:34 AM UTC
Hi Michele,
Thank you for your update.
You are correct this the right approach for reusing the DataTemplate. You have enable the SetCellBoundValue for corresponding column for reuse the DataTemplate.
https://help.syncfusion.com/wpf/datagrid/column-types#reusing-same-datatemplate-for-multiple-columns
Please let us know if you need any further details on this.
Regards,
Farjana Parveen A
SIGN IN To post a reply.
- 3 Replies
- 3 Participants
-
MI Michele
- Sep 2, 2019 09:05 AM UTC
- Sep 9, 2019 10:34 AM UTC