Listview items between space in xamarin forms - xamarin

This is my listview class
public class ListViewClass : ListView
{
public ListViewClass ()
{
var cell = new DataTemplate(typeof(ViewCellClass));
ItemTemplate = cell;
SeparatorVisibility = SeparatorVisibility.None;
this.Style = (Style)Application.Current.Resources["commonBottomMarginThickness"];
HasUnevenRows = true;
}
}
I attached the screenshot. how to put space between the listview items above and below.

Add the value Transparent to your SeparatorColor property.
Like this:
public ListViewClass ()
{
var cell = new DataTemplate(typeof(ViewCellClass));
ItemTemplate = cell;
SeparatorVisibility = SeparatorVisibility.None;
SeparatorColor = Color.Transparent;
this.Style = (Style)Application.Current.Resources["commonBottomMarginThickness"];
HasUnevenRows = true;
}

Related

Bind button in DataTemplate C#

I'm trying to bind a button in a DataTemplate that is being used by a collection view.
This is my button inside the DataTemplate, and I want to bind it to a command in "DetailDayPageViewModel".
Button viewComment = new Button()
{
TextColor = Color.DodgerBlue,
HorizontalOptions = LayoutOptions.Start,
VerticalOptions = LayoutOptions.Start,
FontSize = 16
};
// this binding does not work
viewComment.SetBinding(Button.CommandProperty, nameof(DetailDayPageViewModel.ViewComment));
Use RelativeBinding for binding values of Page's BindingContext to property inside DataTemplate.
There are two ways to do this:
1: Binding through the ViewModel. ReltiveBinding of Mode FindAncestorBindingContext
public class ItemView : Grid
{
public ItemView()
{
Button clickButton = new Button() { Text = "Hi there" };
clickButton.SetBinding(
Button.CommandProperty,
new Binding(
"ItemClickCommand",
source: new RelativeBindingSource(
RelativeBindingSourceMode.FindAncestorBindingContext,
typeof(ViewModel))
));
this.Children.Add(clickButton);
}
}
2: Binding through the Parent view BindingContext:
public class ItemView : Grid
{
public ItemView()
{
Button clickButton = new Button() { Text = "Hi there" };
clickButton.SetBinding(
Button.CommandProperty,
new Binding(
"BindingContext.ItemClickCommand",
source: new RelativeBindingSource(
RelativeBindingSourceMode.FindAncestor,
typeof(CollectionView))
));
this.Children.Add(clickButton);
}
}
Please do check and see if it helps!! Comment for any queries.
I think you can take a look to this sample:
TestBinding
It refers to a ListView, but it should be applicated to a CollectionView.
You need to set the the "source":
TapGestureRecognizer tgrUpDown2 = new TapGestureRecognizer();
tgrUpDown2.SetBinding(TapGestureRecognizer.CommandProperty, new Binding("BindingContext.UpDown2Command", source: this));
tgrUpDown2.SetBinding(TapGestureRecognizer.CommandParameterProperty, ".");
then in your Model, you have the "parameter" passend...
this.UpDown2Command = new Command(async (object obj) =>
{
try
{
if (_isTapped)
return;
if (obj != null)
System.Diagnostics.Debug.WriteLine("Obj is not null");
else
System.Diagnostics.Debug.WriteLine("Obj IS null");
_isTapped = true;
int idx = List.IndexOf((Model)obj);
List[idx].Checked1 = !List[idx].Checked1;
_isTapped = false;
}
catch (Exception ex)
{
_isTapped = false;
await Application.Current.MainPage.DisplayAlert("Attention", ex.Message, "Ok");
}
});
This is a useful link I have found some years ago:
listview-in-xamarin-forms-in-mvvm
If you want a "class" to define your ViewCell, you can assign the class in this way:
lv.ItemTemplate = new DataTemplate(() =>
{
return new MyViewCell(lv);
});
Where MyViewCell is something like:
class MyViewCell : ViewCell
{
public MyViewCell(ListView lv)
{
StackLayout slView = new StackLayout();
slView.SetBinding(StackLayout.BackgroundColorProperty, "BackgroundColor");
Label lDesc = new Label();
lDesc.SetBinding(Label.TextProperty, "Description", stringFormat: "DESCRIPTION: {0}");
lDesc.SetBinding(Label.TextColorProperty, "TextColor");
// LABEL QTY
TapGestureRecognizer tgrQty = new TapGestureRecognizer();
tgrQty.SetBinding(TapGestureRecognizer.CommandProperty, new Binding("BindingContext.QtyCommand", source: lv));
tgrQty.SetBinding(TapGestureRecognizer.CommandParameterProperty, ".");
....
....
View = slView;
}
}
You can pass "ListView" in the constructor so you can use it in "source" binding property.

Add Xamarin.iOS view cell background color and corner radius

I'm trying to add corner radius cell on selected row. I can do it for all but not selected one.
This part of code is not working.
[assembly: ExportRenderer(typeof(ViewCell), typeof(ViewCellItemSelectedCustomRenderer))]
namespace PawsApp.iOS.Renderers
{
public class ViewCellItemSelectedCustomRenderer : ViewCellRenderer
{
private UIView bgView;
public override UITableViewCell GetCell(Cell item, UITableViewCell reusableCell, UITableView tv)
{
UITableViewCell viewCell = base.GetCell(item, reusableCell, tv);
if (viewCell != null)
{
if (bgView == null)
{
bgView = new UIView(viewCell.SelectedBackgroundView.Bounds);
bgView.Layer.BackgroundColor = Color.FromHex("#666495").ToCGColor();
bgView.Layer.CornerRadius = new nfloat(17.5);
}
viewCell.SelectedBackgroundView = bgView;
}
return viewCell;
}
}
}
[assembly: ExportRenderer(typeof(ViewCell), typeof(ViewCellItemSelectedCustomRenderer))]
You can add a subclass of ViewCell in forms and create it's custom renderer. Such as
public class CustomVeggieCell : ViewCell
{
public CustomVeggieCell()
{
//instantiate each of our views
var image = new Image();
var nameLabel = new Label();
var typeLabel = new Label();
var verticaLayout = new StackLayout();
var horizontalLayout = new StackLayout() { BackgroundColor = Color.Olive };
//set bindings
nameLabel.SetBinding(Label.TextProperty, new Binding("Name"));
typeLabel.SetBinding(Label.TextProperty, new Binding("Type"));
image.SetBinding(Image.SourceProperty, new Binding("Image"));
//Set properties for desired design
horizontalLayout.Orientation = StackOrientation.Horizontal;
horizontalLayout.HorizontalOptions = LayoutOptions.Fill;
image.HorizontalOptions = LayoutOptions.End;
nameLabel.FontSize = 24;
//add views to the view hierarchy
verticaLayout.Children.Add(nameLabel);
verticaLayout.Children.Add(typeLabel);
horizontalLayout.Children.Add(verticaLayout);
horizontalLayout.Children.Add(image);
// add to parent view
View = horizontalLayout;
}
}
I have share my sample on github .You can download it for testing.

Carousel View in Xamarin Forms NOT Loading different Templates

public DataTemplate CreateQuestionAnswerRadioButtonTemplate(string question, List<string> answers){
DataTemplate template = new DataTemplate(() =>
{
StackLayout parentLayout = new StackLayout()
{
Padding = new Thickness(20, 20, 20, 20),
HeightRequest = 500,
};
ScrollView surveyScrollView = new ScrollView()
{
Orientation = ScrollOrientation.Vertical,
};
StackLayout questionLayout = new StackLayout()
{
Padding = new Thickness(5, 5, 5, 5),
HeightRequest = 500,
};
Label questLabel = new Label();
questLabel.Text = question;
questLabel.TextColor = Color.FromHex("#EF4D80");
questLabel.FontAttributes = FontAttributes.Bold;
questLabel.FontSize = 18;
BindableRadioGroup radioGroup = new BindableRadioGroup(false);
radioGroup.ItemsSource = answers;
questionLayout.Children.Add(questLabel);
questionLayout.Children.Add(radioGroup);
surveyScrollView.Content = questionLayout;
parentLayout.Children.Add(surveyScrollView);
return parentLayout;
});
return template;
}
Adding these Data Templates to a List.
new CarouselView
{
Margin = new Thickness(0, 20, 0, 0),
ItemsSource = dataTemplates,
ItemTemplate = dataTemplates[0],
};
Now when I swipe the Carousel, How do I load dataTemplates[1 or 2 or 3] ??
I have a Next Button in which in am setting the item source of the Carousel View to dataTemplates[1] but the template does not get updated
Pls Suggest the right approach ?
dataTemplates = new List<DataTemplate>();
dataTemplates.Add(CreateQuestionAnswerRadioButtonTemplate(Constants.SurveyQuestion_1, SurveyQuestion_1_Answers));
dataTemplates.Add(CreateQuestionAnswerRadioButtonTemplate(Constants.SurveyQuestion_3, SurveyQuestion_3_Answers));
dataTemplates.Add(CreateQuestionAnswerRadioButtonTemplate(Constants.SurveyQuestion_4, SurveyQuestion_4_Answers));
dataTemplates.Add(CreateQuestionAnswerRadioButtonTemplate(Constants.SurveyQuestion_5, SurveyQuestion_5_Answers));
You need a DataTemplateSelector for your CarouselView.
in your code behind of the page:
new CarouselView
{
Margin = new Thickness(0, 20, 0, 0),
ItemsSource = dataTemplates,
ItemTemplate = new SurveyDataTemplateSelector()
};
SurveyDataTemplateSelector
DataTemplate survey1Template;
DataTemplate survey3Template;
DataTemplate survey4Template;
DataTemplate survey5Template;
public SurveyDataTemplateSelector()
{
survey1Template = CreateQuestionAnswerRadioButtonTemplate(Constants.SurveyQuestion_1, SurveyQuestion_1_Answers);
survey3Template = CreateQuestionAnswerRadioButtonTemplate(Constants.SurveyQuestion_3, SurveyQuestion_3_Answers);
survey4Template = CreateQuestionAnswerRadioButtonTemplate(Constants.SurveyQuestion_4, SurveyQuestion_4_Answers);
survey5Template = CreateQuestionAnswerRadioButtonTemplate(Constants.SurveyQuestion_5, SurveyQuestion_5_Answers);
}
protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
{
// Here you define which DataTemplate is selected, for example:
if (item == null)
{
return null;
}
SurveyAnswers answers = item as SurveyAnswers;
if (answers.question == 1)
{
return survey1Template;
}
else if (answers.question == 3)
{
return survey3Template;
}
else if (answers.question == 4)
{
return survey4Template;
}
else if (answers.question == 5)
{
return survey5Template;
}
return null;
}
Check this link for a good documentation by Xamarin: https://developer.xamarin.com/guides/xamarin-forms/application-fundamentals/templates/data-templates/selector/

How to Add Content Page to Segment Control in IOS Xamarin.Forms

I have used Segmented Control in my application. I don't know how to add two content pages to Segment control like a tabbed page. I have attached the sample file. Please give any suggestion Link for Sample Application
Sample Code:
public partial class SamplePage : ContentPage
{
SegmentedControl segControl;
SegmentedControlOption optionOne;
SegmentedControlOption optionTwo;
public SamplePage()
{
segControl = new SegmentedControl();
optionOne = new SegmentedControlOption();
optionTwo = new SegmentedControlOption();
optionOne.Text = "One";
optionTwo.Text = "Two";
segControl.Children.Add(optionOne);
segControl.Children.Add(optionTwo);
var stack = new StackLayout()
{
VerticalOptions = LayoutOptions.StartAndExpand,
HorizontalOptions = LayoutOptions.CenterAndExpand,
Children = { segControl }
};
this.Content = stack;
}
}
ScreenShot Attached
Just some suggestions and explanations.
We can't put a ContentPage inside another ContentPage
It's better to use ContentView instead of ContentPage
Grid is more recommended in this scenario , since it fills with the whole Screen.
Use ValueChanged event to change the view dynamically.
Code :
Page
public partial class SegmentedAppPage : ContentPage
{
SegmentedControl segControl;
SegmentedControlOption scOptionOne;
SegmentedControlOption scOptionTwo;
Grid grid;
View1 view1 = new View1();
View2 view2 = new View2();
public SegmentedAppPage()
{
InitializeComponent();
segControl = new SegmentedControl();
segControl.SelectedValue = "One";
scOptionOne = new SegmentedControlOption();
scOptionTwo = new SegmentedControlOption();
scOptionOne.Text = "One";
scOptionTwo.Text = "Two";
segControl.Children.Add(scOptionOne);
segControl.Children.Add(scOptionTwo);
grid = new Grid();
grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Auto) });
grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) });
grid.Children.Add(segControl, 0, 0);
grid.Children.Add(view1, 0, 1);
this.Content = grid;
segControl.ValueChanged += SegControl_ValueChanged;
}
private void SegControl_ValueChanged(object sender, EventArgs e)
{
SegmentedControl control = sender as SegmentedControl;
if(control.SelectedValue is "One")
{
grid.Children.Remove(view2);
grid.Children.Add(view1,0,1); //This line
}
else if (control.SelectedValue is "Two")
{
grid.Children.Remove(view1);
grid.Children.Add(view2, 0, 1); //This line
}
this.Content = grid;
}
}
ContentView
public class View1 : ContentView
{
public View1()
{
Content = new StackLayout
{
BackgroundColor = Color.Green,
Children = {
new Label { Text = "View1" }
}
};
}
}
To set default value on segmentedControl , modify code in SegmentedControlRenderers
protected override void OnElementChanged(ElementChangedEventArgs<SegmentedControl> e)
{
base.OnElementChanged(e);
var segmentedControl = new UISegmentedControl();
for (var i = 0; i < e.NewElement.Children.Count; i++)
{
segmentedControl.InsertSegment(e.NewElement.Children[i].Text, i, false);
}
segmentedControl.ValueChanged += (sender, eventArgs) => {
e.NewElement.SelectedValue = segmentedControl.TitleAt(segmentedControl.SelectedSegment);
};
segmentedControl.SelectedSegment = 0; // add this line
SetNativeControl(segmentedControl);
}
Test

Access ListView Item Data

I'm setting the ItemSource of a listview and trying to create multiple Labels within the listview DataTemplate based on the children of a property of that particular item (the items are gigs, and they have a list of band members and im trying to list the band members).
I'm not sure how to get the properties of the current item that's having it's template created, can someone help?
ListView listView = new ListView {
ItemsSource = viewModel.gigs,
ItemTemplate = new DataTemplate (() => {
var grid = new Grid();
grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star)});
for(int x = 0;x<=viewModel.bandMembers.Count;x++) {
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star)});
}
var venueName = new Label { Text = "Top Left" };
venueName.SetBinding (Label.TextProperty, "Venue");
grid.Children.Add(venueName, 0, 0);
for(int x = 0;x<THISITEM.bandMembers.Count;x++) {
grid.Children.Add(new Label() {Text="Test"},x,0);
}
return new ViewCell { View = grid };
});
// Build the page.
this.Content = new StackLayout {
Children = {
header,
listView
}
};
You can override OnBindingContextChnaged function in ViewCell and get the ItemData from BindingContext

Resources