Well the previous solution does work for OneWay but I just can't figure out how to get it to work both ways. Editing data in the grid is seriously painful....
So I have these generated columns :
foreach (Criteria criteria in criterias)
{
GridTemplateColumn newColumn = new GridTemplateColumn();
newColumn.MappingName = "Scores";
newColumn.DisplayBinding = new Binding("Scores",
BindingMode.TwoWay,
GetCellTemplateCriteriaConverter(criteria),
criteria.ID);
newColumn.HeaderText = criteria.Name;
newColumn.HeaderTemplate = headerCell;
newColumn.CellTemplate = new DataTemplate(() => GetCellTemplateForCriteria(criteria));
newColumn.Width = GetColumnWidthForCriteria(criteria);
DataGrid.Columns.Add(newColumn);
}
The template for each criteria goes as follows :
private StackLayout GetCellTemplateForCriteria(Criteria criteria)
{
StackLayout result = GetSimplePropertyCellTemplate(criteria.Type,
"placeholder",
(int)criteria.MinValue,
(int)criteria.MaxValue,
(int)criteria.DefaultValue);
foreach (View child in result.Children)
{
BindableProperty editValueProperty;
if (child is Label)
{
editValueProperty = Label.TextProperty;
}
else
{
switch (criteria.Type)
{
case CriteriaType.IntRange:
case CriteriaType.Number:
{
editValueProperty = IntRangeSegmentControl.ValueProperty;
break;
}
case CriteriaType.Text:
{
editValueProperty = Entry.TextProperty;
break;
}
case CriteriaType.Time:
{
editValueProperty = TimePicker.TimeProperty;
break;
}
default:
{
editValueProperty = Entry.TextProperty;
break;
}
}
}
child.SetBinding(editValueProperty,
new Binding("Scores",
BindingMode.TwoWay,
GetCellTemplateCriteriaConverter(criteria),
criteria.ID));
}
return result;
}
private StackLayout GetSimplePropertyCellTemplate(CriteriaType cellType, string mappingName, int minRange = 0, int maxRange = 10, int defaultValue = 0)
{
StackLayout result = null;
result = new StackLayout();
Label valueLabel = new Label();
View editControl;
BindableProperty editValueProperty;
valueLabel.VerticalOptions = LayoutOptions.CenterAndExpand;
valueLabel.HorizontalOptions = LayoutOptions.CenterAndExpand;
valueLabel.SetBinding(Label.TextProperty, new Binding(mappingName, BindingMode.OneWay));
valueLabel.SetBinding(IsVisibleProperty,
new Binding("Editable",
BindingMode.OneWay,
Application.Current.Resources["InvertBool"] as IValueConverter));
switch (cellType)
{
case CriteriaType.IntRange:
case CriteriaType.Number:
{
editControl = new IntRangeSegmentControl(minRange, maxRange, defaultValue);
editValueProperty = IntRangeSegmentControl.ValueProperty;
break;
}
case CriteriaType.Text:
{
editControl = new Entry();
editValueProperty = Entry.TextProperty;
break;
}
case CriteriaType.Time:
{
editControl = new TimePicker();
editValueProperty = TimePicker.TimeProperty;
break;
}
default:
{
editControl = new Entry();
editValueProperty = Entry.TextProperty;
break;
}
}
editControl.VerticalOptions = LayoutOptions.CenterAndExpand;
editControl.HorizontalOptions = LayoutOptions.CenterAndExpand;
editControl.SetBinding(editValueProperty, new Binding(mappingName, BindingMode.TwoWay));
editControl.SetBinding(HeightRequestProperty, new Binding("Editable", BindingMode.OneWay, new HeightInvisibleValueConverter()));
result.VerticalOptions = LayoutOptions.CenterAndExpand;
result.HorizontalOptions = LayoutOptions.CenterAndExpand;
result.Children.Add(valueLabel);
result.Children.Add(editControl);
result.Margin = ColumnsHorizontalPadding;
return result;
}
private IValueConverter GetCellTemplateCriteriaConverter(Criteria criteria)
{
string converterId = "StringScoresFacade";
switch (criteria.Type)
{
case CriteriaType.IntRange:
case CriteriaType.Number:
{
converterId = "IntScoresFacade";
break;
}
}
return Application.Current.Resources[converterId] as IValueConverter;
}
My converter doesn't get called when I set the value in a control within the template... Why?