it's possible to binding TextColor property label in GroupHeaderTemplate?
this is my source code:
<ListView.GroupHeaderTemplate>
<DataTemplate>
<ViewCell Height="25">
<StackLayout VerticalOptions="FillAndExpand" Padding="5"
BackgroundColor="#0477B3">
<Label Text="{Binding Key, Converter={StaticResource dateConverter}}"
TextColor="#ffffff" VerticalOptions="Center"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.GroupHeaderTemplate>
br
Max
The BindingContext for a group is the grouping itself. Without knowing more about your code here is an example of how to bind to the grouping object in the group header template:
<ListView ItemsSource="{Binding}"
IsGroupingEnabled="true" GroupDisplayBinding="{ Binding Name }"
GroupShortNameBinding ="{ Binding ShortName }">
<ListView.GroupHeaderTemplate>
<DataTemplate>
<ViewCell Height="25">
<StackLayout VerticalOptions="FillAndExpand" Padding="5"
BackgroundColor="#0477B3">
<!-- Name refers to Group.Name, depeding on your data you can use the key of your grouping here -->
<Label Text="{Binding Name}" VerticalOptions="Center"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.GroupHeaderTemplate>
<ListView.ItemTemplate>
<DataTemplate>
<TextCell Text="{ Binding Title }" Detail="{ Binding Description }" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
And the code:
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
ObservableCollection<Group> groupedItems = new ObservableCollection<Group>();
Group group = new Group("First Group");
groupedItems.Add(group);
Item item = new Item("First Item", "First Item Description");
group.Add(item);
this.BindingContext = groupedItems;
}
}
public class Item
{
public String Title { get; private set; }
public String Description { get; private set; }
public Item(String title, String description)
{
Title = title;
Description = description;
}
}
public class Group : ObservableCollection<Item>
{
public String Name { get; private set; }
public Group(String Name)
{
this.Name = Name;
}
}
Example taken and modified from here
Related
I have a Picker which i have populated with object data from the model. The challenge am facing is that when i tap on the picker to select an item, the list is empty. And also when i specify the ItemsDisplayBinding to one of the model properties. The items are displayed with weird names in the form of app-name.Model for example if app name is cool App, items are displayed as cool-app.Model.ModelName...
What could i be doing wrong? This is my code please.
// xaml file
<ContentPage
xmlns:model="clr-namespace:SoftFashions.Model"
xmlns:viewmodel="clr-namespace:SoftFashions.ViewModel"
x:DataType="viewmodel:ShoppingBagViewModel">
<Grid RowDefinitions="Auto,200,*"
RowSpacing="0"
ColumnDefinitions="*,*">
<CollectionView
ItemsSource="{Binding ShoppingBagCollection}"
Grid.Row="1"
Grid.ColumnSpan="2"
EmptyView="NO ITEMS ADDED">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="model:Cloth">
<!-- controls displaying shoppingBagCollection data-->
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
<Grid
Grid.ColumnSpan="2"
Grid.Row="2"
Padding="0"
Grid.ColumnDefinitions="*,*"
Grid.RowDefinitions="*,*,*,*"
ColumnSpacing="0"
HorizontalOptions="FillAndExpand"
Margin="20">
<VerticalStackLayout
Grid.RowSpan="4"
Grid.Column="0">
<Label Grid.Row="0"
Text="LOCATION"
TextColor="{StaticResource Primary}"
Style="{StaticResource MediumLabel}"
FontAttributes="Bold"/>
<!-- picker to display items from the PickupStations collection-->
<Picker
x:Name="picker"
TextColor="Black"
Grid.Row="1"
Title="SELECT LOCATION"
FontAttributes="Italic"
ItemsSource="{Binding PickupStations}"
ItemDisplayBinding="{Binding Location}"
SelectedItem="{Binding SelectedItem}"
/>
<!-- entry to display text depending on selected item from the picker-->
<Entry x:Name="shippingfeeLabel"
Grid.Row="2"
Text="{Binding SelectedItem.Shippingfee}"
WidthRequest="120"
HorizontalOptions="Start"
Placeholder="$0.00"
Margin="0,15,0,0"
IsReadOnly="True"/>
<Entry Grid.Row="2"
Text="shipping fee"
IsReadOnly="True"
Margin="0,0,0,0"/>
</VerticalStackLayout>
</Grid>
</ContentPage>
// view model
/*variables*/
[ObservableProperty]
Pickupstations selectedItem;
public ObservableCollection<Pickupstations> PickupStations { get; } = new();
ClothService clothService;
//Constructor
public ShoppingBagViewModel()
{
this.clothService = new();
}
// getting pickup stations from the service
[RelayCommand]
public async Task<ObservableCollection<Pickupstations>> DisplayPickupstationsAsync()
{
try
{
var pickuplists = await clothService.GetPickupstations();
if (PickupStations.Count > 0)
PickupStations.Clear();
foreach (var pickuplist in pickuplists)
{
PickupStations.Add(pickuplist);
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
return PickupStations;
}
}
// Model
public class Pickupstations
{
public string Name { get; }
public string Location { get; }
public string Shippingfee { get; }
}
Ofcourse the service fetches data from the internet from where the viewmodel picks up the data
please help me out with this...Many thanks
You can directly assign the PickupStations via the ClothService in the ViewModel constructor. I write a pseudo ClothService.cs to generate the data source of the picker and extract the key element for your reference below:
Xaml:
<Picker
x:Name="picker"
TextColor="Black"
Title="SELECT LOCATION"
FontAttributes="Italic"
ItemsSource="{Binding PickupStations}"
ItemDisplayBinding="{Binding Location}"
SelectedItem="{Binding SelectedItem}"/>
ViewModel:
public partial class MainViewModel : ObservableObject
{
[ObservableProperty]
Pickupstations selectedItem;
public ObservableCollection<Pickupstations> PickupStations { get; } = new();
public MainViewModel()
{
PickupStations = clothService.GetPickstations();
}
}
ClothService.cs:
public class clothService
{
public static ObservableCollection<Pickupstations> GetPickstations()
{
var locations = new ObservableCollection<Pickupstations>()
{
new Pickupstations{Name="Bob", Location="Italy"},
new Pickupstations{Name="Rock", Location="Greek"},
new Pickupstations{Name="John", Location="Argetina"},
};
return locations;
}
}
Model:
public class Pickupstations
{
public string Name { get; set; }
public string Location { get; set; }
}
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 ListView which in its DataTemplate has a ViewCell with 2 Labels. What I want to do is that the size of the ListView is proportional to the text that these two Labels have. If they don't contain text, make the ListView very small, if it contains a lot of text, make the size large.
Thats my actual code:
<ListView HasUnevenRows="True" HeightRequest="{Binding heightList}" ItemsSource="{Binding sourceList}" SelectionMode="Single" SeparatorColor="Transparent" SeparatorVisibility="None">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout>
<Label FontSize="14" LineBreakMode="NoWrap" Text="{Binding text1}" />
<Label FontSize="14" LineBreakMode="NoWrap" Text="{Binding text2}" />
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Can you just not bind isVisible to if text1/text2 is not ""? like
bool IsTxt1Vis { get { return text1 != ""; } }
What I want to do is that the size of the ListView is proportional to the text that these two Labels have. If they don't contain text, make the ListView very small, if it contains a lot of text, make the size large.
According to your description, you want to adjust height of listview to be minimum size to fit children? If yes, you can use binding ListView HeightRequestto do.
firstly, please set ListView VerticalOptions="StartAndExpand",otherwise the listview's heightrequest in StackLayout will be ignored.
<StackLayout>
<ListView
BackgroundColor="AliceBlue"
HasUnevenRows="True"
HeightRequest="{Binding rowHeigth}"
ItemsSource="{Binding sourceList}"
MinimumHeightRequest="50"
VerticalOptions="StartAndExpand">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout>
<Label
FontSize="14"
LineBreakMode="NoWrap"
Text="{Binding text1}" />
<Label
FontSize="14"
LineBreakMode="NoWrap"
Text="{Binding text2}" />
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<Button
x:Name="addbtn"
Command="{Binding AddCommand}"
Text=" add data in listview" />
</StackLayout>
public partial class Page5 : ContentPage
{
public Page5()
{
InitializeComponent();
this.BindingContext = new listviewmodel();
}
}
public class listviewmodel:ViewModelBase
{
public ObservableCollection<listmodel> sourceList { get; set; }
private int _rowHeigth;
public int rowHeigth
{
get { return _rowHeigth; }
set
{
_rowHeigth = value;
RaisePropertyChanged("rowHeigth");
}
}
public ICommand AddCommand { protected set; get; }
public listviewmodel()
{
sourceList = new ObservableCollection<listmodel>()
{
new listmodel(){text1="test 1",text2="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"},
new listmodel(){text1="test 1",text2="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"},
new listmodel(){text1="test 1bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",text2="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacccccccccccccccccccccccccccc"},
new listmodel(){text1="test 1",text2="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"},
new listmodel(){text1="test 1",text2="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}
};
rowHeigth = sourceList.Count * 40;
AddCommand = new Command<listmodel>(async (key) => {
sourceList.Add(new listmodel() { text1 = "test 1", text2 = "aaaaaaaaaa" });
rowHeigth = sourceList.Count * 40;
});
}
}
public class listmodel
{
public string text1 { get; set; }
public string text2 { get; set; }
}
The ViewModelBase is class that implementing INotifyPropertyChanged interface.
public class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
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;
}