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
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
this.grid_Source.ItemsSource = itemSource;
is the way i am populating the datagrid control.
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;
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; }
}
}
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
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
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
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