I have a CollectionView with a GridItemsLayout with a list of subjects as the ItemsSource. I want the footer to appear at the end of the CollectionView as if it were the last item, but at this time, it simply appears at the vertical end of the list.
Screenshot of what is currently happening
Here is the CollectionView XAML:
<CollectionView x:Name="collectionViewSubjects">
<CollectionView.ItemsLayout>
<GridItemsLayout Span="2" HorizontalItemSpacing="15" VerticalItemSpacing="20"
Orientation="Vertical"/>
</CollectionView.ItemsLayout>
<CollectionView.ItemTemplate>
<DataTemplate>
<border:SfBorder Style="{DynamicResource listItemBorder}">
<AbsoluteLayout HeightRequest="180">
<gradient:SfGradientView AbsoluteLayout.LayoutFlags="All"
AbsoluteLayout.LayoutBounds="0.5, 0.5, 1, 1"
Style="{StaticResource subjectItemGradient}"/>
<Label Text="{Binding Name}"
AbsoluteLayout.LayoutFlags="All"
AbsoluteLayout.LayoutBounds="0.5, 0.1, 0.9, 0.2"
FontAttributes="Bold"/>
<Label Text="{Binding Credits, StringFormat='0 / {0} credits'}"
AbsoluteLayout.LayoutFlags="All"
AbsoluteLayout.LayoutBounds="0.5, 0.35, 0.9, 0.2"/>
<Label Text="{Binding Standards, StringFormat='{0} standards'}"
AbsoluteLayout.LayoutFlags="All"
AbsoluteLayout.LayoutBounds="0.5, 0.53, 0.9, 0.2"/>
<Button:SfButton Text="View Info" CornerRadius="30"
TextColor="Black"
FontAttributes="Bold"
FontSize="17"
AbsoluteLayout.LayoutFlags="All"
AbsoluteLayout.LayoutBounds="0.5, 0.85, 0.7, 0.2"
Style="{StaticResource subjectButtonGradient}"/>
</AbsoluteLayout>
</border:SfBorder>
</DataTemplate>
</CollectionView.ItemTemplate>
<CollectionView.Footer>
<border:SfBorder Style="{DynamicResource listItemBorder}"
BackgroundColor="Black"
HeightRequest="180">
<Button Text="Add Subject"
TextColor="Yellow"
BackgroundColor="Transparent"/>
</border:SfBorder>
</CollectionView.Footer>
</CollectionView>
Edit: Here is my code-behind for the same page:
SubjectsPageViewModel ViewModel;
public SubjectsPage()
{
InitializeComponent();
ViewModel = new SubjectsPageViewModel();
BindingContext = ViewModel;
collectionViewSubjects.ItemsSource = ViewModel.Subjects;
//var model =
//model.IsVisible = true;
}
You could define the Button in DataTemplate in advance . And set the property IsVisible as true of the last item .
<DataTemplate>
<StackLayout>
<border:SfBorder IsVisible="{Binding IsVisible,Converter={StaticResource BoolConverter}}" Style="{DynamicResource listItemBorder}">
<AbsoluteLayout HeightRequest="180">
//...
</AbsoluteLayout>
</border:SfBorder>
<border:SfBorder IsVisible="{Binding IsVisible}" Style="{DynamicResource listItemBorder}"
BackgroundColor="Black"
HeightRequest="180">
<Button Text="Add Subject"
TextColor="Yellow"
BackgroundColor="Transparent"/>
</border:SfBorder>
</StackLayout>
</DataTemplate>
public class xxxModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
bool isVisible=false; // the button is invisible in default
public bool IsVisible
{
get
{
return isVisible;
}
set
{
if (isVisible != value)
{
isVisible = value;
NotifyPropertyChanged("IsVisible");
}
}
}
//other properties
}
Create a converter
public class BoolConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var isVisible = (bool)value;
return !isVisible;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
invoke the following line after you initialize the ItemSource
var model = ItemSource[ItemSource.Count - 1] as xxxModel;
model.IsVisible = true;