This is a migrated thread and some comments may be shown as answers.

How to enable selections on the RadDataGrid when binding a data template

10 Answers 350 Views
DataGrid
This is a migrated thread and some comments may be shown as answers.
Akash
Top achievements
Rank 1
Akash asked on 09 May 2018, 02:05 PM

i am able to bind data to a data grid using data templates but i am trying to get in a position to start selecting items from the grid, how can i do this using the

RadDataGrid for Xamarin forms: 

Xaml : 

<dg:RadDataGrid SelectionMode="Single"                         
                        Margin="0,20,0,0" 
                        HorizontalOptions="Center" 
                        SelectionUnit="Row" x:Name="grid_Source">
        </dg:RadDataGrid>

 

Code Behind - 

List<MetaData> src = new List<MetaData>();
            src.Add(new MetaData { Id = "Data", Caption = "Data" });
            src.Add(new MetaData { Caption = "Select", Id = "Select" });
            src.Add(new MetaData { Caption = "OperatorNo", Id = "OperatorNo" });
            src.Add(new MetaData { Caption = "OperatorName", Id = "OperatorName" });

            foreach (MetaData columns in src)
            {
                String propertyName = $"[{columns.Id}].Value";
                Telerik.XamarinForms.DataGrid.DataGridTemplateColumn text_Column = 
                    new Telerik.XamarinForms.DataGrid.DataGridTemplateColumn();
                text_Column.HeaderText = columns.Caption;
                text_Column.Name = propertyName;
                text_Column.CellContentTemplate = GetTemplate(propertyName,"Button", columns.Caption);

                this.grid_Source.Columns.Add(text_Column);
            }
            
            this.grid_Source.SelectionUnit = Telerik.XamarinForms.DataGrid.DataGridSelectionUnit.Row;
            this.grid_Source.SelectionStyle = new Telerik.XamarinForms.DataGrid.DataGridBorderStyle
            {
                BackgroundColor = Color.Orange,
                BorderColor = Color.Orange,
                BorderThickness = new Thickness(2)
            };

            this.grid_Source.AutoGenerateColumns = false;

 

Data Template :

 

public DataTemplate GetTemplate(String psPropertyName, String ControlType, String ColumnCaption)
        {
            return new DataTemplate(() =>
            {
                View oView = null;
                Label oLabel = new Label()
                {
                    BackgroundColor = Color.Transparent,
                    TextColor = Color.Black,
                    VerticalOptions = LayoutOptions.FillAndExpand,
                    HorizontalOptions = LayoutOptions.FillAndExpand
                };
                oLabel.SetBinding(Label.TextProperty, psPropertyName);

                oView = oLabel;
                return new Xamarin.Forms.StackLayout()
                {
                    Children = {
                                oView,
                },
                    Margin = new Thickness(0),
                    Padding = new Thickness(0),
                    HeightRequest = 50
                };
            });
        }

        

10 Answers, 1 is accepted

Sort by
0
Lance | Manager Technical Support
Telerik team
answered on 10 May 2018, 01:52 PM
Hello Akash,

The TemplateCell's CellDecorator can sometimes overlay the the row style (SelectionStyle would occupy the same vertical space here). You can try the following CellDecorationStyle:

new DataGridTemplateColumn
{
    HeaderText = columns.Caption,
    Name = propertyName,
    CellContentTemplate = GetTemplate(propertyName, "Button", columns.Caption),
    CellDecorationStyle = new DataGridBorderStyle {BorderThickness = new Thickness(0), BorderColor = Color.Transparent}
}

Note that I am not able to confirm that this is a fix for you, as the code you've provided doesn't populate the DataGrid with any data. If this doesn't work, please reply back with the other classes and code that populates the DataGrid so that I may be able to fully test your scenario.

If you need the assistance of the UI for Xamarin development team, you can open a support ticket to contact them.

Regards,
Lance | Tech Support Engineer, Sr.
Progress Telerik
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
Akash
Top achievements
Rank 1
answered on 11 May 2018, 08:25 AM

this.grid_Source.ItemsSource = itemSource;

 

is the way i am populating the datagrid control. 

0
Akash
Top achievements
Rank 1
answered on 11 May 2018, 08:26 AM
all i am trying to do is select a row and highlight it in a different color using the above approach. 
0
Akash
Top achievements
Rank 1
answered on 11 May 2018, 08:33 AM

            List<DataValue> itemSource = new List<DataValue>();
            itemSource.Add(new DataValue { Id = "Data", Value = "Data" });
            itemSource.Add(new DataValue { Id = "Select", Value = "Select" });
            itemSource.Add(new DataValue { Id = "OperatorNo", Value = "OperatorNo" });

 

this.grid_Source = itemSource;

 

0
Akash
Top achievements
Rank 1
answered on 11 May 2018, 08:37 AM

using Grid_Source.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
using Grid_Source.ViewModels;
using System.Collections.ObjectModel;
using Grid_Source.Template;

namespace Grid_Source
{
    public partial class MainPage : ContentPage
    {
        DataTemplate FromTemplate;
        DataTemplate ToTemplate;

        public MainPage() : base()
        {
            InitializeComponent();
            BindingContext = new BaseViewModel();
        }

        protected override void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            base.OnPropertyChanged(propertyName);
            switch (propertyName)
            {

                case nameof(BindingContext):
                    Create_Table();
                    break;
            }
        }

        private void Create_Table()
        {
            List<MetaData> src = new List<MetaData>();
            src.Add(new MetaData { Id = "Data", Caption = "Data" });
            src.Add(new MetaData { Caption = "Select", Id = "Select" });
            src.Add(new MetaData { Caption = "OperatorNo", Id = "OperatorNo" });
            src.Add(new MetaData { Caption = "OperatorName", Id = "OperatorName" });


            List<DataValue> itemSource = new List<DataValue>();
            itemSource.Add(new DataValue { Id = "Data", Value = "Data" });
            itemSource.Add(new DataValue { Id = "Select", Value = "Select" });
            itemSource.Add(new DataValue { Id = "OperatorNo", Value = "OperatorNo" });

            foreach (MetaData columns in src)
            {
                String propertyName = $"[{columns.Id}].Value";
                String val_ue = ".Value";
                Telerik.XamarinForms.DataGrid.DataGridTemplateColumn text_Column =
                    new Telerik.XamarinForms.DataGrid.DataGridTemplateColumn();
                text_Column.HeaderText = columns.Caption;
                text_Column.Name = propertyName;

                text_Column.CellContentTemplate = GetTemplate(val_ue, "Button", columns.Caption);
                text_Column.CellDecorationStyle = new Telerik.XamarinForms.DataGrid.DataGridBorderStyle
                {
                    BorderThickness = new Thickness(0),
                    BorderColor = Color.Orange
                };
                this.grid_Source.Columns.Add(text_Column);
            }

            this.grid_Source.SelectionUnit = Telerik.XamarinForms.DataGrid.DataGridSelectionUnit.Row;
            this.grid_Source.SelectionStyle = new Telerik.XamarinForms.DataGrid.DataGridBorderStyle
            {
                BackgroundColor = Color.Orange,
                BorderColor = Color.Orange,
                BorderThickness = new Thickness(2)
            };

            this.grid_Source.SelectionChanged += Grid_Source_SelectionChanged;
            this.grid_Source.AutoGenerateColumns = false;
            this.grid_Source.SetBinding(Telerik.XamarinForms.DataGrid.RadDataGrid.ItemsSourceProperty, "_display");
        }

        private void Grid_Source_SelectionChanged(object sender, Telerik.XamarinForms.DataGrid.DataGridSelectionChangedEventArgs e)
        {
            throw new NotImplementedException();
        }

        public DataTemplateSelector SetTemplate(String propertyName, String ControlType, String Caption)
        {
            TemplateSelector selector = new TemplateSelector();

            selector.FromTemplate = new DataTemplate(() =>
            {
                View oView = null;
                Label oLabel = new Label()
                {
                    TextColor = Color.Black,
                    VerticalOptions = LayoutOptions.FillAndExpand,
                    HorizontalOptions = LayoutOptions.FillAndExpand
                };
                oLabel.SetBinding(Label.TextProperty, propertyName);

                oView = oLabel;
                return new Xamarin.Forms.StackLayout()
                {
                    Children = {
                                oView,
                },
                    Margin = new Thickness(0),
                    Padding = new Thickness(0),
                    HeightRequest = 50,
                    BackgroundColor = Color.Orange
                };
            });

            selector.ToTemplate = new DataTemplate(() =>
            {
                View oView = null;
                Label oLabel = new Label()
                {
                    TextColor = Color.Red,
                    VerticalOptions = LayoutOptions.FillAndExpand,
                    HorizontalOptions = LayoutOptions.FillAndExpand
                };
                oLabel.SetBinding(Label.TextProperty, propertyName);

                oView = oLabel;
                return new Xamarin.Forms.StackLayout()
                {
                    Children = {
                                oView,
                },
                    Margin = new Thickness(0),
                    Padding = new Thickness(0),
                    HeightRequest = 50,
                    BackgroundColor = Color.Blue
                };
            });

            return selector;
        }

 




        public DataTemplate GetTemplate(String psPropertyName, String ControlType, String ColumnCaption)
        {
            return new DataTemplate(() =>
            {
                View oView = null;
                Label oLabel = new Label()
                {
                    BackgroundColor = Color.Transparent,
                    TextColor = Color.Black,
                    VerticalOptions = LayoutOptions.FillAndExpand,
                    HorizontalOptions = LayoutOptions.FillAndExpand
                };
                oLabel.SetBinding(Label.TextProperty, psPropertyName);

                oView = oLabel;
                return new Xamarin.Forms.StackLayout()
                {
                    Children = {
                                oView,
                },
                    Margin = new Thickness(0),
                    Padding = new Thickness(0),
                    HeightRequest = 50
                };
            });
        }
    }
}

 

ViewModel :- 

 

using System ;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Text;

namespace Grid_Source.ViewModels
{
    public class BaseViewModel : INotifyPropertyChanged
    {
        //populate grid.
        private ObservableCollection<Dictionary<String, DataValue>> _source = null;

        public ObservableCollection<Dictionary<String, DataValue>> _display
        {
            get
            {

                return displaySource();
            }
            set
            {
                _source = displaySource();
            }
        }

        private ObservableCollection<DataValue> obj = null;

        public ObservableCollection<DataValue> src_db
        {
            get
            {
                return SingleObject();
            }

            set
            {
                obj = SingleObject();
            }
        }



        public event PropertyChangedEventHandler PropertyChanged;

        public ObservableCollection<Dictionary<String, DataValue>> displaySource()
        {

            ObservableCollection<Dictionary<String, DataValue>> src_db = new ObservableCollection<Dictionary<string, DataValue>>();
            Dictionary<String, DataValue> collect = new Dictionary<string, DataValue>();
            collect.Add("Data", new DataValue { Id = "Data", Value = "Data" });
            collect.Add("Select", new DataValue { Id = "Select", Value = "Select" });
            collect.Add("OperatorNo", new DataValue { Id = "OperatorNo", Value = "OperatorNo" });
            collect.Add("OperatorName", new DataValue { Id = "OperatorName", Value = "OperatorName" });
            src_db.Add(collect);
            this._source = src_db;
            return src_db;
        }

        public ObservableCollection<DataValue> SingleObject()
        {
            ObservableCollection<DataValue> src = new ObservableCollection<DataValue>();
            src.Add(new DataValue { Id = "Data", Value = "Data" });
            src.Add(new DataValue { Id = "Select", Value = "Select" });
            src.Add(new DataValue { Id = "OperatorNo", Value = "OperatorNo" });
            src.Add(new DataValue { Id = "OperatorName", Value = "OperatorName" });
            

            return src;
        }
    }

    

    public class DataValue
    {
        public string Id { get; set; }

        public string Value { get; set; }
    }

    public class NotifyPropertyChanged : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        public void RaisePropertyChanged(String psPropertyName)
        {

            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(psPropertyName));
        }
    }

    public class MetaData
    {
        public string Caption { get; set; }

        public string Id { get; set; }
    }
}


0
Lance | Manager Technical Support
Telerik team
answered on 11 May 2018, 07:27 PM
Hello Akash,

I don't see any problem with the selection style, I've used your code and get a result where the DataGrid has a row but the cell templates are not working. You can however still see the orange selection when you tap in the area.

I recommend reviewing the cell template's content and make sure the background is transparent. As a place to start, try just adding the items directly to the StackLayout instead of placing inside a View with an opaque background.

Demo

To help clarify, I've changed the demo to replace the missing data with hard coded value for oLabel and removed the View from the template.

public DataTemplate GetTemplate(String psPropertyName, String ControlType, String ColumnCaption)
{
    return new DataTemplate(() =>
    {
        var stackLayout = new StackLayout();
 
        Label oLabel = new Label()
        {
            BackgroundColor = Color.Transparent,
            TextColor = Color.Black,
            VerticalOptions = LayoutOptions.FillAndExpand,
            HorizontalOptions = LayoutOptions.FillAndExpand,
        };
 
        //oLabel.SetBinding(Label.TextProperty, psPropertyName);
        oLabel.Text = "Lorem Ipsum";
 
        stackLayout.Children.Add(oLabel);
 
        return stackLayout;
    });
}


Here's the result at runtime when you select the row:


Because the StackLayout and Label have transparent backgrounds, the row selection shows.  For your convenience, I've attached the demo here so you can see this first hand.

Regards,
Lance | Tech Support Engineer, Sr.
Progress Telerik
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
Akash
Top achievements
Rank 1
answered on 14 May 2018, 07:49 AM
However this is for programmatic selection, it would be the same code for a gesture driven selection right? 
0
Lance | Manager Technical Support
Telerik team
answered on 14 May 2018, 02:25 PM
Hello Akash,

As long as you're setting the DataGrid.SelectedItem to on of the items in the ItemsSource, yes. For example, assuming you set up the SelectedItem with two-way binding:

grid_Source.SetBinding(RadDataGrid.SelectedItemProperty, new Binding("SelectedDisplayItem", BindingMode.TwoWay));

You can select an item programmatically using one of the items in the items source, this line selects the first item:

viewModel.SelectedDisplayItem = viewModel.DisplayItems.FirstOrDefault();


Demo

For example,if the view model had the following code:

public class BaseViewModel : INotifyPropertyChanged
{
    private ObservableCollection<DataValue> displayItems;
    private DataValue selectedDisplayItem;
 
 
    public ObservableCollection<DataValue> DisplayItems
    {
        get => displayItems ?? (displayItems = GetDisplayItems());
        set
        {
            if (displayItems == value) return;
            displayItems = value;
            OnPropertyChanged();
        }
    }
 
    public DataValue SelectedDisplayItem
    {
        get => selectedDisplayItem;
        set
        {
            if (selectedDisplayItem == value) return;
            selectedDisplayItem = value;
            OnPropertyChanged();
        }
    }
 
    private ObservableCollection<DataValue> GetDisplayItems()
    {
        var srcDb = new ObservableCollection<DataValue>()
        {
            new DataValue { Id = "Data", Value = "Data", Caption = "Data"},
            new DataValue { Id = "Select", Value = "Select", Caption = "Select"},
            new DataValue { Id = "OperatorNo", Value = "OperatorNo", Caption = "OperatorNo"},
            new DataValue { Id = "OperatorName", Value = "OperatorName", Caption = "OperatorName"}
        };
 
        return srcDb;
    }
 
    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}


You could do the following to set up the DataGrid:

public partial class MainPage : ContentPage
{
    private readonly BaseViewModel viewModel;
 
    public MainPage()
    {
        InitializeComponent();
        viewModel = new BaseViewModel();
        BindingContext = viewModel;
 
        SetUpDataGrid();
    }
 
    private void SetUpDataGrid()
    {
        grid_Source.AutoGenerateColumns = false;
        grid_Source.SelectionUnit = DataGridSelectionUnit.Row;
        grid_Source.SelectionStyle = new DataGridBorderStyle
        {
            BackgroundColor = Color.Orange,
            BorderColor = Color.Orange,
            BorderThickness = new Thickness(2)
        };
 
        var properties = typeof(DataValue).GetProperties();
 
        foreach (PropertyInfo property in properties)
        {
            grid_Source.Columns.Add(new DataGridTemplateColumn
            {
                HeaderText = property.Name,
                Name = property.Name,
                CellContentTemplate = GetTemplate(property.Name, "Button", property.Name),
                CellDecorationStyle = new DataGridBorderStyle
                {
                    BorderThickness = new Thickness(0),
                    BorderColor = Color.Orange
                }
            });
        }
 
        // Set the ItemsSource
        grid_Source.SetBinding(RadDataGrid.ItemsSourceProperty, new Binding("DisplayItems"));
 
        // Set the SelectedItem using two-way binding
        grid_Source.SetBinding(RadDataGrid.SelectedItemProperty, new Binding("SelectedDisplayItem", BindingMode.TwoWay));
 
        // Now, you can programmatically set the selected item vbecause of the two-way binding
        // For example, if you wanted to select the first item in the list
        viewModel.SelectedDisplayItem = viewModel.DisplayItems.FirstOrDefault();
    }
 
    public DataTemplate GetTemplate(string psPropertyName, string controlType, string columnCaption)
    {
        return new DataTemplate(() =>
        {
                // Using StackLayout instead of View
                var stackLayout = new StackLayout();
 
            var oLabel = new Label()
            {
                BackgroundColor = Color.Transparent,
                TextColor = Color.Black,
                VerticalOptions = LayoutOptions.FillAndExpand,
                HorizontalOptions = LayoutOptions.FillAndExpand,
            };
 
            oLabel.SetBinding(Label.TextProperty, psPropertyName);
                //oLabel.Text = "Lorem Ipsum";
 
                stackLayout.Children.Add(oLabel);
 
            return stackLayout;
        });
    }
}

Then you'll end up with the following at runtime as soon as the page opens:




Regards,
Lance | Tech Support Engineer, Sr.
Progress Telerik
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
Gary
Top achievements
Rank 1
answered on 13 Sep 2018, 04:05 PM

Hi Lance,

I have been having a similar problem with selection when using DataTemplateColumns.

I've tried the Visual Studio solution that you posted - and this seems to work with the UWP project, but I can't get the selection to show on Android - either in the emulator or on an actual device.

Is there anything else I can try?

Regards,

Gary

 

0
Lance | Manager Technical Support
Telerik team
answered on 13 Sep 2018, 07:09 PM
Hi Gary,

Without seeing your code I can't tell for sure, but if you set the CellContentTemplate contents to not intercept the tap gesture, it should resolve the issue.

Here's an example:

<dataGrid:DataGridTemplateColumn HeaderText="Template Column">
    <dataGrid:DataGridTemplateColumn.CellContentTemplate>
        <DataTemplate>
            <Grid InputTransparent="True">
                <!-- Your content -->
            </Grid>
        </DataTemplate>
    </dataGrid:DataGridTemplateColumn.CellContentTemplate>
</dataGrid:DataGridTemplateColumn>


If this doesn't help, please open a Support Ticket (you have priority technical support) and attach the files related to your DataGrid implementation (view, view model etc). I'll see the ticket come in and will investigate directly.

Regards,
Lance | Tech Support Engineer, Sr.
Progress Telerik
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
Tags
DataGrid
Asked by
Akash
Top achievements
Rank 1
Answers by
Lance | Manager Technical Support
Telerik team
Akash
Top achievements
Rank 1
Gary
Top achievements
Rank 1
Share this question
or