We use cookies to give you the best experience on our website. If you continue to browse, then you agree to our privacy policy and cookie policy. Image for the cookie policy date

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

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, 
 
 
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. 
 
 
Please let us know if you need any further details on this. 
 
Regards, 
Farjana Parveen A 


Loader.
Live Chat Icon For mobile
Up arrow icon