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

11 posts, 0 answers
  1. Akash
    Akash avatar
    6 posts
    Member since:
    Feb 2018

    Posted 09 May 2018 Link to this post

    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
                    };
                });
            }

            

  2. Lance | Manager Technical Support
    Admin
    Lance | Manager Technical Support avatar
    1186 posts

    Posted 10 May 2018 Link to this post

    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
  3. Akash
    Akash avatar
    6 posts
    Member since:
    Feb 2018

    Posted 11 May 2018 Link to this post

    this.grid_Source.ItemsSource = itemSource;

     

    is the way i am populating the datagrid control. 

  4. Akash
    Akash avatar
    6 posts
    Member since:
    Feb 2018

    Posted 11 May 2018 in reply to Akash Link to this post

    all i am trying to do is select a row and highlight it in a different color using the above approach. 
  5. Akash
    Akash avatar
    6 posts
    Member since:
    Feb 2018

    Posted 11 May 2018 in reply to Akash Link to this post

                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;

     

  6. Akash
    Akash avatar
    6 posts
    Member since:
    Feb 2018

    Posted 11 May 2018 in reply to Akash Link to this post

    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; }
        }
    }


  7. Lance | Manager Technical Support
    Admin
    Lance | Manager Technical Support avatar
    1186 posts

    Posted 11 May 2018 Link to this post

    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
  8. Akash
    Akash avatar
    6 posts
    Member since:
    Feb 2018

    Posted 14 May 2018 in reply to Lance | Manager Technical Support Link to this post

    However this is for programmatic selection, it would be the same code for a gesture driven selection right? 
  9. Lance | Manager Technical Support
    Admin
    Lance | Manager Technical Support avatar
    1186 posts

    Posted 14 May 2018 Link to this post

    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
  10. Gary
    Gary avatar
    3 posts
    Member since:
    Jul 2012

    Posted 13 Sep 2018 in reply to Lance | Manager Technical Support Link to this post

    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

     

  11. Lance | Manager Technical Support
    Admin
    Lance | Manager Technical Support avatar
    1186 posts

    Posted 13 Sep 2018 Link to this post

    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
Back to Top