I would like to databind a custom class when displayed in xmal, but I'm getting nothing displayed in the list view. Any pointers to what I'm missing would be much appreciated.
public Transactional()
{
string oCustomerLoggedIn = Preferences.Get("uLoginUsername", "default_value");
int oCustomerLoggedInId = GetCustomerId(oCustomerLoggedIn);
List<TransactionsList> custTransactions = ViewCustomerTransactions(oCustomerLoggedInId);
InitializeComponent();
listView.SetBinding(ListView.ItemsSourceProperty, new Binding("."));
listView.BindingContext = custTransactions;
}
<ListView x:Name="listView" ItemSelected="OnItemSelected">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.ContextActions>
<MenuItem Clicked="OnMore" CommandParameter="{Binding .}" Text="More" />
<MenuItem Clicked="OnDelete" CommandParameter="{Binding .}" Text="Delete" IsDestructive="True" />
</ViewCell.ContextActions>
<StackLayout HorizontalOptions="StartAndExpand" Orientation="Horizontal">
<StackLayout Padding="5,0,0,0" VerticalOptions="StartAndExpand" Orientation="Vertical">
<Label Text="{Binding .}" VerticalTextAlignment="Center" FontSize="Medium" />
</StackLayout>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Try this, refactor and modify where appropriate ...
List Item Model ...
using System;
namespace Playpen
{
public class ListItem
{
public string Text { get; set; }
public string SubText { get; set; }
}
}
XAML ...
<?xml version="1.0" encoding="utf-8"?>
<ContentPage
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:Playpen"
x:Class="Playpen.MainPage">
<StackLayout VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
<ListView
ItemsSource="{Binding DataSource}"
HasUnevenRows="true"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand"
SeparatorColor="Silver">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand" Padding="10">
<Label Text="{Binding Text}" FontSize="Medium" FontAttributes="Bold" LineBreakMode="TailTruncation"
TextColor="Black" VerticalOptions="Start" HorizontalOptions="StartAndExpand" />
<Label Text="{Binding SubText}" FontSize="Small" Margin="0, 5, 0, 0" LineBreakMode="TailTruncation"
TextColor="Gray" VerticalOptions="Start" HorizontalOptions="StartAndExpand" />
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage>
Page Code Behind (you can refactor to MVVM as you need) ...
using System;
using System.Collections.ObjectModel;
using Xamarin.Forms;
namespace Playpen
{
public partial class MainPage : ContentPage
{
public ObservableCollection<ListItem> DataSource { get; set; }
public MainPage()
{
this.BindingContext = this;
DataSource = new ObservableCollection<ListItem>();
DataSource.Add(new ListItem() { Text = "Item 1", SubText = "Sub Item Text 1" });
DataSource.Add(new ListItem() { Text = "Item 2", SubText = "Sub Item Text 2" });
DataSource.Add(new ListItem() { Text = "Item 3", SubText = "Sub Item Text 3" });
InitializeComponent();
}
}
}
Related
So I have a xamarin forms app that currently only implemented for android. I am attempting to implement a tap event. When tapped though this never hits the command in the ViewModel. I'm not sure if I have something the matter with my code or I am just implementing it wrong.
ViewModel Code:
private RelayCommand<object> _OnClickableLabel;
public RelayCommand<object> OnClickableLabel
{
get { return _OnClickableLabel ?? (_OnClickableLabel = new RelayCommand<object>((currentObject) => Test(currentObject))); }
}
private void Test(object currentObject)
{
Application.Current.MainPage.DisplayAlert("Alert", "were going down cap", "OK");
}
Page Xaml:
<ListView Grid.Row="1" ItemsSource="{Binding Notifications}" RowHeight="100">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Vertical" BackgroundColor="{Binding BackgroundColor}">
<StackLayout.GestureRecognizers>
<TapGestureRecognizer Command="{Binding OnClickableLabel }" />
</StackLayout.GestureRecognizers>
<Label FontSize="Large" Text="{Binding Title}"></Label>
<Label FontSize="Small" Text="{Binding Text}"></Label>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
I have tested it using a method in the page's cs code and that works fine but it has to be implemented in the ViewModel because it affects that data.
From your description, you want to add a tap gesture recognizer in ListView, and want to pass ListView current row data to TapGestureRecognizer event, am I right?
If yes, as Jason's opinion, you need to take a look Xamarin.Forms Relative Bindings firstly,name ListView as listview1, then take a look the following code:
<ListView
x:Name="listview1"
Grid.Row="1"
ItemsSource="{Binding Notifications}"
RowHeight="100">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout BackgroundColor="{Binding BackgroundColor}" Orientation="Vertical">
<StackLayout.GestureRecognizers>
<TapGestureRecognizer Command="{Binding BindingContext.OnClickableLabel, Source={x:Reference listview1}}" CommandParameter="{Binding .}" />
</StackLayout.GestureRecognizers>
<Label FontSize="Large" Text="{Binding Title}" />
<Label FontSize="Small" Text="{Binding Text}" />
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
public partial class Page16 : ContentPage
{
public ObservableCollection<Notclass> Notifications { get; set; }
public ICommand OnClickableLabel { get; set; }
public Page16()
{
InitializeComponent();
Notifications = new ObservableCollection<Notclass>()
{
new Notclass(){Title="title 1",Text="notification 1"},
new Notclass(){Title="title 2",Text="notification 2"},
new Notclass(){Title="title 3",Text="notification 3"},
new Notclass(){Title="title 4",Text="notification 4"},
new Notclass(){Title="title 5",Text="notification 5"}
};
OnClickableLabel = new Command(n=> {
var vm = (Notclass)n;
Application.Current.MainPage.DisplayAlert("Alert",vm.Title , "OK");
});
this.BindingContext = this;
}
}
public class Notclass
{
public string Title { get; set; }
public string Text { get; set; }
public Color BackgroundColor { get; set; } = Color.White;
}
I have a CollectionView:
<CollectionView Grid.Row="10" Grid.Column="0" Grid.ColumnSpan="1" x:Name="SomeCollection"
ItemsLayout="VerticalList">
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout Orientation="Horizontal" Padding="3" Spacing="0">
<Label WidthRequest="90" HeightRequest="20" Text="{Binding SomeItemText}" BackgroundColor="Black" TextColor="White"
VerticalTextAlignment="Center" HorizontalTextAlignment="Center" />
<Button WidthRequest="36" HeightRequest="36" CornerRadius="0" ImageSource="plus_thick.xml" BackgroundColor="Green"
Clicked="Duplicate_Clicked" />
<Button WidthRequest="36" HeightRequest="36" CornerRadius="0" ImageSource="close_thick.xml" BackgroundColor="Red"
Clicked="Remove_Clicked" />
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
Every item in the collection has a duplicate and a remove button. By clicking the button I would like to duplicate/remove the item, but CollectionView doesn't have indexes on items.
Could you help me with a custom renderer or even something shorter and simpler?
About getting current collectionview item index by Button command, I do one sample that you can take a look:
<StackLayout>
<CollectionView
x:Name="SomeCollection"
ItemsLayout="VerticalList"
ItemsSource="{Binding items}">
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout
Padding="3"
Orientation="Horizontal"
Spacing="0">
<Label
BackgroundColor="Black"
HeightRequest="20"
HorizontalTextAlignment="Center"
Text="{Binding SomeItemText}"
TextColor="White"
VerticalTextAlignment="Center"
WidthRequest="90" />
<Button
BackgroundColor="Green"
Command="{Binding BindingContext.duplicatecommand, Source={x:Reference SomeCollection}}"
CommandParameter="{Binding}"
CornerRadius="0"
HeightRequest="36"
Text="duplicate item"
WidthRequest="36" />
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</StackLayout>
public partial class Page13 : ContentPage
{
public ObservableCollection<someitems> items { get; set; }
public ICommand duplicatecommand { get; set; }
public Page13()
{
InitializeComponent();
items = new ObservableCollection<someitems>()
{
new someitems(){SomeItemText="test 1"},
new someitems(){SomeItemText="test 2"},
new someitems(){SomeItemText="test 3"},
new someitems(){SomeItemText="test 4"},
new someitems(){SomeItemText="test 5"},
new someitems(){SomeItemText="test 6"}
};
duplicatecommand = new Command<someitems>(getindexfun);
this.BindingContext = this;
}
private void getindexfun(someitems item)
{
int index = items.IndexOf(item);
}
}
public class someitems
{
public string SomeItemText { get; set; }
}
Instead of using click events, I would bind the buttons to a Command<T>.
This way in the ViewModel where you have your ItemsSource, you can just check what the index is of the Item ViewModel you are passing into the command as parameter. So in the ViewModel add something like this:
public Command<ItemViewModel> RemoveItemCommand { get; }
ctor() // this is the ViewModel constructor
{
RemoveItemCommand = new Command<ItemViewModel>(DoRemoveItemCommand);
}
private void DoRemoveItemCommand(ItemViewModel model)
{
// do stuff to remove
// probably something like:
Items.Remove(model);
// or get the index like:
var index = Items.IndexOf(model);
}
Then you can bind this command like so:
<Button
WidthRequest="36"
HeightRequest="36"
CornerRadius="0"
ImageSource="close_thick.xml"
BackgroundColor="Red"
Command="{Binding Source={RelativeSource AncestorType={x:Type local:ItemViewModel}}, Path=RemoveItemCommand}"
CommandParameter="{Binding}" />
I am having issues with displaying data, I can see my data FieldValue and FieldDescriptor in the List property however I still see in output that:
Binding: 'Results' property not found on 'ViewModel.ResultPageViewModel', target property: 'Xamarin.Forms.ListView.ItemsSource'
I can't see any data FieldVisualData in the horizontal list view even thought I can see them in the view model adding to detail and the command also can't be found.
Binding: 'EditTextCommand' property not found on 'Model.DocumentData', target property: 'Xamarin.Forms.TapGestureRecognizer.Command'
Maybe you see something that I am missing?
<StackLayout Spacing="0">
<!--Pictures-->
<StackLayout VerticalOptions="Start" Spacing="0" >
<controls:HorizontalScrollList VerticalOptions="Start" HeightRequest="300" x:Name="carouselView" ItemsSource="{Binding Results, Mode=TwoWay}">
<controls:HorizontalScrollList.ItemTemplate>
<DataTemplate>
<Image Source="{Binding Results.FieldVisualData}"
Margin="5">
<!--<Image.GestureRecognizers>
<TapGestureRecognizer
Command="{Binding HandlePreviewTapped, Source={x:Reference vm}}"
CommandParameter="{Binding}"/>
</Image.GestureRecognizers>-->
</Image>
</DataTemplate>
</controls:HorizontalScrollList.ItemTemplate>
</controls:HorizontalScrollList>
</StackLayout>
<StackLayout VerticalOptions="Start" BackgroundColor="{DynamicResource SeparatorLineColor}" Spacing="10">
<!--DocumentData-->
<Label Grid.Row="0" HorizontalOptions="CenterAndExpand" Text="Občanský průkaz" VerticalOptions="End" ></Label>
<StackLayout BackgroundColor="{DynamicResource PageBackgroundColor}" VerticalOptions="FillAndExpand">
<ListView x:Name="list" BackgroundColor="{DynamicResource PageBackgroundColor}"
HasUnevenRows="True"
HorizontalOptions="CenterAndExpand"
VerticalOptions="CenterAndExpand"
VerticalScrollBarVisibility="Never"
CachingStrategy="RecycleElement"
ItemsSource="{Binding Results, Mode=TwoWay}"
SeparatorVisibility="Default"
SelectionMode="None">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid BackgroundColor="{DynamicResource PageBackgroundColor}" Padding="10" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="15*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="12*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Grid.Column="1" Padding="0" Text ="{Binding FieldDescriptor}" Style="{StaticResource SubLabelBlackStyle}" HorizontalOptions="Start" BackgroundColor="{DynamicResource PageBackgroundColor}" HorizontalTextAlignment="Start"/>
<Label Grid.Column="3" Padding="0" Text="{Binding FieldValue}" FontSize="Small" TextColor="#6781a3" BackgroundColor="{DynamicResource PageBackgroundColor}" HorizontalOptions="Start" HorizontalTextAlignment="Start">
<Label.GestureRecognizers>
<TapGestureRecognizer Command="{Binding EditTextCommand}" CommandParameter="{Binding FieldValue}" />
</Label.GestureRecognizers>
</Label>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</StackLayout>
</StackLayout>
public partial class ResultPage : ContentPage
{
public ResultPage(IEnumerable<DocumentData> data)
{
InitializeComponent();
BindingContext = new ResultPageViewModel(data);
//carouselView.ItemsSource = data;
// list.ItemsSource = data;
}
}
public class ResultPageViewModel : BaseViewModel
{
public ObservableCollection<DocumentData> Results { get; } = new ObservableCollection<DocumentData>();
public ICommand EditTextCommand { get; }
object param = "";
public ResultPageViewModel(IEnumerable<DocumentData> data)
{
EditTextCommand = new Command(async () => await EditTextAsync(param));
Load(data);
}
public void Load(IEnumerable<DocumentData> data)
{
foreach (var result in data)
{
var detail = new DocumentData()
{
FieldVisualData = result.FieldVisualData,
FieldDescriptor = result.FieldDescriptor,
FieldValue = result.FieldValue,
};
Results.Add(detail);
}
}
public async Task EditTextAsync(object param)
{
PromptResult pResult = await UserDialogs.Instance.PromptAsync(new PromptConfig
{
InputType = InputType.Password,
Text = param.ToString(),
Title = Resources.AppResources.Password_lbl,
});
}
}
public static readonly BindableProperty ItemTemplateProperty = BindableProperty.Create(
"ItemTemplate",
typeof(DataTemplate),
typeof(HorizontalScrollList),
null,
propertyChanged: (bindable, value, newValue) => ((HorizontalScrollList)bindable).Populate());
public static readonly BindableProperty ItemsSourceProperty = BindableProperty.Create(
"ItemsSource",
typeof(IEnumerable),
typeof(HorizontalScrollList),
null,
BindingMode.OneWay,
propertyChanged: (bindable, value, newValue) =>
{
var obs = value as INotifyCollectionChanged;
var self = (HorizontalScrollList)bindable;
if (obs != null)
obs.CollectionChanged -= self.HandleItemChanged;
self.Populate();
obs = newValue as INotifyCollectionChanged;
if (obs != null)
obs.CollectionChanged += self.HandleItemChanged;
});
public IEnumerable ItemsSource
{
get => (IEnumerable)this.GetValue(ItemsSourceProperty);
set => this.SetValue(ItemsSourceProperty, value);
}
public DataTemplate ItemTemplate
{
get => (DataTemplate)this.GetValue(ItemTemplateProperty);
set => this.SetValue(ItemTemplateProperty, value);
}
private bool willUpdate = true;
private void HandleItemChanged(object sender, NotifyCollectionChangedEventArgs eventArgs)
{
if (!willUpdate)
{
willUpdate = true;
Device.BeginInvokeOnMainThread(Populate);
}
}
public HorizontalScrollList()
{
this.Orientation = ScrollOrientation.Horizontal;
}
private void Populate()
{
willUpdate = false;
Content = null;
if (ItemsSource == null || ItemTemplate == null)
{
return;
}
var list = new StackLayout { Orientation = StackOrientation.Horizontal };
foreach (var viewModel in ItemsSource)
{
var content = ItemTemplate.CreateContent();
if (!(content is View) && !(content is ViewCell))
{
throw new Exception($"Invalid visual object {nameof(content)}");
}
var view = content is View ? content as View : ((ViewCell)content).View;
view.BindingContext = viewModel;
list.Children.Add(view);
}
if (list.Children.Count == 0)
{
list.Padding = 20;
list.Children.Add(new Label
{
WidthRequest = (list as VisualElement).Width - 30,
HorizontalOptions = new LayoutOptions(LayoutAlignment.Fill, true),
VerticalOptions = new LayoutOptions(LayoutAlignment.Fill, true),
HorizontalTextAlignment = TextAlignment.Center,
VerticalTextAlignment = TextAlignment.Center,
FontSize = 15,
});
}
Content = list;
}
Do you want to acheve the result like following GIF?
I do not which style or backgroundcolor that you setted, I set it with static background color.
Here is my editted layout.controls:HorizontalScrollList is a picture, so I comment it.
I change the Command in the TapGestureRecognizer
<StackLayout Spacing="0">
<!--Pictures-->
<StackLayout VerticalOptions="Start" Spacing="0" >
<!--<controls:HorizontalScrollList VerticalOptions="Start" HeightRequest="300" x:Name="carouselView" ItemsSource="{Binding Results, Mode=TwoWay}">
<controls:HorizontalScrollList.ItemTemplate>
<DataTemplate>
<Image Source="{Binding Results.FieldVisualData}"
Margin="5">
--><!--<Image.GestureRecognizers>
<TapGestureRecognizer
Command="{Binding HandlePreviewTapped, Source={x:Reference vm}}"
CommandParameter="{Binding}"/>
</Image.GestureRecognizers>--><!--
</Image>
</DataTemplate>
</controls:HorizontalScrollList.ItemTemplate>
</controls:HorizontalScrollList>-->
</StackLayout>
<StackLayout VerticalOptions="Start" BackgroundColor="White" Spacing="10">
<!--DocumentData-->
<Label Grid.Row="0" HorizontalOptions="CenterAndExpand" Text="Občanský průkaz" VerticalOptions="End" ></Label>
<StackLayout BackgroundColor="Green" VerticalOptions="FillAndExpand">
<ListView x:Name="list" BackgroundColor="Red"
HasUnevenRows="True"
HorizontalOptions="CenterAndExpand"
VerticalOptions="CenterAndExpand"
VerticalScrollBarVisibility="Never"
CachingStrategy="RecycleElement"
ItemsSource="{Binding Results, Mode=TwoWay}"
SeparatorVisibility="Default"
SelectionMode="None">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid BackgroundColor="Beige" Padding="10" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="15*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="12*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Grid.Column="1" Padding="0" Text ="{Binding FieldDescriptor}" HorizontalOptions="Start" BackgroundColor="Gray" HorizontalTextAlignment="Start"/>
<Label Grid.Column="3" Padding="0" Text="{Binding FieldValue}" FontSize="Small" TextColor="#6781a3" BackgroundColor="AliceBlue" HorizontalOptions="Start" HorizontalTextAlignment="Start">
<Label.GestureRecognizers>
<TapGestureRecognizer
Command="{Binding BindingContext.EditTextCommand, Source={x:Reference Name=list}}"
CommandParameter="{Binding .}"
/>
</Label.GestureRecognizers>
</Label>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</StackLayout>
</StackLayout>
Here is layout background code. I add three data to make a test.
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
IEnumerable<DocumentData> data = new DocumentData[] { new DocumentData() { FieldDescriptor="test 1", FieldValue=1, FieldVisualData=1 } };
data = data.Append(new DocumentData() { FieldDescriptor = "test 2", FieldValue = 2, FieldVisualData = 2 });
data = data.Append(new DocumentData() { FieldDescriptor = "test 3", FieldValue = 3, FieldVisualData = 3 });
this.BindingContext = new ResultPageViewModel(data);
}
}
Here is ResultPageViewModels code.
using Acr.UserDialogs;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using Xamarin.Forms;
namespace XFormsListviewMvvm
{
public class ResultPageViewModel : BaseViewModel
{
public ObservableCollection<DocumentData> Results { get; } = new ObservableCollection<DocumentData>();
public ICommand EditTextCommand { get; }
object param = "";
public ResultPageViewModel(IEnumerable<DocumentData> data)
{
EditTextCommand = new Command<DocumentData>(async (key) => await EditTextAsync(key));
Load(data);
}
public void Load(IEnumerable<DocumentData> data)
{
foreach (var result in data)
{
var detail = new DocumentData()
{
FieldVisualData = result.FieldVisualData,
FieldDescriptor = result.FieldDescriptor,
FieldValue = result.FieldValue,
};
Results.Add(detail);
}
}
public async Task EditTextAsync(DocumentData param)
{
PromptResult pResult = await UserDialogs.Instance.PromptAsync(new PromptConfig
{
InputType = InputType.Password,
Text = param.FieldValue.ToString(),
Title = "Insert your Password",
});
if (pResult.Ok)
{
param.FieldValue = pResult.Text;
}
}
}
}
If you need to change the value, then layout will display it. you need to implement the BaseViewModel in the DocumentData.
namespace XFormsListviewMvvm
{
public class DocumentData:BaseViewModel
{
private object fieldVisualData = "Hello world";
public object FieldVisualData
{
get => fieldVisualData;
set => SetValue(ref fieldVisualData, value);
}
private object fieldValue = "Hello world";
public object FieldValue
{
get => fieldValue;
set => SetValue(ref fieldValue, value);
}
public object FieldDescriptor { get; internal set; }
}
}
=============Update===================
I add your controls:HorizontalScrollList code. And I change the from <Image Source="{Binding Results.FieldVisualData}"> to <Image Source="{Binding FieldVisualData}" >
Here is running gif.Image could be seen normally.
Here is editted layout.
<StackLayout Spacing="0">
<!--Pictures-->
<StackLayout VerticalOptions="Start" Spacing="0" >
<controls:HorizontalScrollList VerticalOptions="Start" HeightRequest="300" x:Name="carouselView" ItemsSource="{Binding Results, Mode=TwoWay}">
<controls:HorizontalScrollList.ItemTemplate>
<DataTemplate>
<Image Source="{Binding FieldVisualData}"
Margin="5">
<!--<Image.GestureRecognizers>
<TapGestureRecognizer
Command="{Binding HandlePreviewTapped, Source={x:Reference vm}}"
CommandParameter="{Binding}"/>
</Image.GestureRecognizers>-->
</Image>
</DataTemplate>
</controls:HorizontalScrollList.ItemTemplate>
</controls:HorizontalScrollList>
</StackLayout>
<StackLayout VerticalOptions="Start" BackgroundColor="White" Spacing="10">
<!--DocumentData-->
<Label Grid.Row="0" HorizontalOptions="CenterAndExpand" Text="Občanský průkaz" VerticalOptions="End" ></Label>
<StackLayout BackgroundColor="Green" VerticalOptions="FillAndExpand">
<ListView x:Name="list" BackgroundColor="Red"
HasUnevenRows="True"
HorizontalOptions="CenterAndExpand"
VerticalOptions="CenterAndExpand"
VerticalScrollBarVisibility="Never"
CachingStrategy="RecycleElement"
ItemsSource="{Binding Results, Mode=TwoWay}"
SeparatorVisibility="Default"
SelectionMode="None">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid BackgroundColor="Beige" Padding="10" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="15*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="12*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Grid.Column="1" Padding="0" Text ="{Binding FieldDescriptor}" HorizontalOptions="Start" BackgroundColor="Gray" HorizontalTextAlignment="Start"/>
<Label Grid.Column="3" Padding="0" Text="{Binding FieldValue}" FontSize="Small" TextColor="#6781a3" BackgroundColor="AliceBlue" HorizontalOptions="Start" HorizontalTextAlignment="Start">
<Label.GestureRecognizers>
<TapGestureRecognizer
Command="{Binding BindingContext.EditTextCommand, Source={x:Reference Name=list}}"
CommandParameter="{Binding .}"
/>
</Label.GestureRecognizers>
</Label>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</StackLayout>
</StackLayout>
Here is layout background code.
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
IEnumerable<DocumentData> data = new DocumentData[] { new DocumentData() { FieldDescriptor="test 1", FieldValue=1, FieldVisualData= "https://aka.ms/campus.jpg" } };
data = data.Append(new DocumentData() { FieldDescriptor = "test 2", FieldValue = 2, FieldVisualData = "https://aka.ms/campus.jpg" });
data = data.Append(new DocumentData() { FieldDescriptor = "test 3", FieldValue = 3, FieldVisualData = "https://aka.ms/campus.jpg" });
this.BindingContext = new ResultPageViewModel(data);
}
}
I have a CaruselPage and inside the DataTemplate I have put a CollectionView
<CarouselPage.ItemTemplate>
<DataTemplate>
<ContentPage>
<ContentPage.Content>
<StackLayout>
<CollectionView
ItemsSource="{Binding Cards}"
VerticalOptions="CenterAndExpand"
HorizontalOptions="Center"
EmptyView="Non ci sono Card Formazione"
Margin="10"
x:Name="CV"
>
<CollectionView.ItemsLayout>
<GridItemsLayout Orientation="Vertical" Span="1" />
</CollectionView.ItemsLayout>
<CollectionView.ItemTemplate>
<DataTemplate>
<Frame BorderColor="Black">
<StackLayout>
<Label Text="{Binding DisciplinaCard}" Style="{StaticResource LabelTesStyle}"/>
<Label Text="{Binding DataCard}" Style="{StaticResource LabelTesStyle}"/>
</StackLayout>
</Frame>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</StackLayout>
</StackLayout>
</ContentPage.Content>
</ContentPage>
</DataTemplate>
</CarouselPage.ItemTemplate>
I manage to populate the carusel page but I can't find how to populate the collection view.
All the solution that I find is for UWP, but I need to do this in xamarin.forms cross platform.
According to your description, you want to add collectionview control in CaruselPage, I do one sample that you can take a look.
Here is the CaruselPage:
<CarouselPage
x:Class="CaruselApp.MainPage"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">
<CarouselPage.ItemTemplate>
<DataTemplate>
<ContentPage>
<StackLayout>
<Label Margin="10" Text="{Binding title}" />
<CollectionView ItemsSource="{Binding collections}">
<CollectionView.ItemsLayout>
<GridItemsLayout Orientation="Vertical" Span="1" />
</CollectionView.ItemsLayout>
<CollectionView.ItemTemplate>
<DataTemplate>
<Frame BorderColor="Black">
<StackLayout>
<Label Text="{Binding Name}" />
<Label Text="{Binding Age}" />
</StackLayout>
</Frame>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</StackLayout>
</ContentPage>
</DataTemplate>
</CarouselPage.ItemTemplate>
The Model in CollectionView:
public class CollectionModel
{
public string Name { get; set; }
public int Age { get; set; }
}
The Model in CarouselPage:
public class CaruselModel
{
public ObservableCollection<CollectionModel> collections { get; set; }
public string title { get; set; }
public static ObservableCollection<CaruselModel> carusels { get; set; }
static CaruselModel()
{
carusels = new ObservableCollection<CaruselModel>()
{
new CaruselModel(){title="title 1", collections=new ObservableCollection<CollectionModel>(){ new CollectionModel() { Name="Cherry",Age=12},new CollectionModel() { Name="barry",Age=23} } },
new CaruselModel(){title="title 2", collections=new ObservableCollection<CollectionModel>(){ new CollectionModel() { Name="Annine",Age=18},new CollectionModel() { Name="Wendy",Age=25} } },
new CaruselModel(){title="title 3", collections=new ObservableCollection<CollectionModel>(){ new CollectionModel() { Name="Mattew",Age=12},new CollectionModel() { Name="Leo",Age=23} } },
new CaruselModel(){title="title 4", collections=new ObservableCollection<CollectionModel>(){ new CollectionModel() { Name="Jessie",Age=12},new CollectionModel() { Name="Junior",Age=23} } },
new CaruselModel(){title="title 5", collections=new ObservableCollection<CollectionModel>(){ new CollectionModel() { Name="Jack",Age=12},new CollectionModel() { Name="Land",Age=23} } }
};
}
}
Please don't forget to add the following code in Android Mainactivity or ios AppDelegate, because you use CollectionView.
Forms.SetFlags("CollectionView_Experimental");
Here is the sample at Github, you can download to test.
https://github.com/CherryBu/CarouselApp
her is the screenshot:
I would like to get the value of a selectedItem in A listView,this is my code.
public class BlogClass{
public string NewId;
public BlogClass()
{
additem();
}
public class BlogViews
{
public string id { get; set; }
public string DisplayTopic { get; set; }
public string DisplayMain { get; set; }
public ImageSource BlogImageSource { get; set; }
}
public List<BlogViews> BlogList1 = new List<BlogViews>();
public void additem()
{
BlogList1.Add(new BlogViews { id = "1", DisplayMain = "Margret", DisplayTopic = "Mensah" });
BlogList1.Add(new BlogViews { id = "2", DisplayMain = "Maet", DisplayTopic = "Meah" });
BlogList1.Add(new BlogViews { id = "3", DisplayMain = "dargret", DisplayTopic = "sah" });
BlogList1.Add(new BlogViews { id = "4", DisplayMain = "gret", DisplayTopic = "Meh" });
BlogListView.ItemsSource = BlogList1;
}
}
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="demoListView.ImageCellPage">
<ContentPage.Content>
<ListView x:Name="BloglistView">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout BackgroundColor="#eee"
Orientation="Vertical">
<StackLayout Orientation="Horizontal">
<Image Source="{Binding BlogImageSource}" />
<Label Text="{Binding id}"
TextColor="#f35e20" />
<Label Text="{Binding DisplayTopic}"
HorizontalOptions="EndAndExpand"
TextColor="#503026" />
<Label Text="{Binding DisplayMain}"
HorizontalOptions="EndAndExpand"
TextColor="#503026" />
</StackLayout>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentPage.Content>
</ContentPage>
Question
Now When i select an item on BlogListView I want to set the Value of NewId to that of id according to the selecteditem.Hence gatting the value of id
You just need to add ItemTapped event for the listview:
XAML:
<ListView x:Name="BloglistView" ItemTapped="Handle_ItemTapped">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout BackgroundColor="#eee"
Orientation="Vertical">
<StackLayout Orientation="Horizontal">
<Image Source="{Binding BlogImageSource}" />
<Label Text="{Binding id}"
TextColor="#f35e20" />
<Label Text="{Binding DisplayTopic}"
HorizontalOptions="EndAndExpand"
TextColor="#503026" />
<Label Text="{Binding DisplayMain}"
HorizontalOptions="EndAndExpand"
TextColor="#503026" />
</StackLayout>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Code Behind:
void Handle_ItemTapped(object sender, Xamarin.Forms.ItemTappedEventArgs e)
{
var selectedItem = e.Item as BlogViews;
NewId = selectedItem.id;
}