Reputation: 1781
I have a sample project where I am trying to do two things as identified below. All properties are in the same ViewModel.
I am attempting to hide the header by setting the visibility of all the objects in the HeaderTemplate to false by binding the visibility property to a property in my viewmodel. This is not working. What I really want is a way to turn on and off the header, in code is fine but I would prefer in XAML. All the code is below. Any suggestions would be appreciated.
NOTE: I have already tried putting all the Header properties into their own class, instantiating an instance of the class in my ViewModel and setting the Header Binding to that class with each header label binding to a property of that class. This did not work either.
XAML Code
<?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:SampleHeaderFooter"
x:Class="SampleHeaderFooter.MainPage">
<ContentPage.Content>
<!-- List of places -->
<ListView x:Name="lvPlaces"
VerticalOptions="StartAndExpand"
HorizontalOptions="StartAndExpand"
HasUnevenRows="True"
ItemsSource="{Binding GBSPlaceDetails}"
Header="{Binding HeaderText}">
<ListView.HeaderTemplate>
<DataTemplate>
<StackLayout IsVisible="False">
<Label x:Name="lblHeaderText" Text="{Binding .}" IsVisible="{Binding HeaderVisible}" TextColor="White" FontSize="Medium" FontAttributes="Bold" />
<Label x:Name="lblHeaderLink" Text="Click here to change your settings." IsVisible="{Binding HeaderVisible}"
TextColor="Blue" FontSize="Medium" FontAttributes="Bold">
<Label.GestureRecognizers>
<TapGestureRecognizer Tapped="btnSettings_Clicked"/>
</Label.GestureRecognizers>
</Label>
</StackLayout>
</DataTemplate>
</ListView.HeaderTemplate>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<BoxView x:Name="bvLine" Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" VerticalOptions="Center" HorizontalOptions="FillAndExpand" BackgroundColor="Black" HeightRequest="1" />
<Label x:Name="lblPlaceName" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" BackgroundColor="Transparent" TextColor="Gray" FontAttributes="Bold"
Text="{Binding Title}" FontSize="Medium" Margin="0,4,0,4" VerticalOptions="Center" HorizontalOptions="FillAndExpand"/>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentPage.Content>
Code Behind
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
namespace SampleHeaderFooter
{
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
PlacesVM lobj_PlaceVM = new PlacesVM();
BindingContext = lobj_PlaceVM;
}
private void btnSettings_Clicked(object sender, EventArgs e)
{
}
}
}
ViewModelClass
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SampleHeaderFooter
{
public class GBSPlaceDetail
{
/// <summary>
/// Name / Title of the Place
/// </summary>
public string Title { get; set; }
}
public class PlacesVM
{
private bool ib_HeaderVisible = false;
private string is_HeaderText = "";
/// <summary>
/// Indicates if the header should be visible. This only happens when a query was performed using the values as specified in the settings and no locations
/// were returned.
/// </summary>
public bool HeaderVisible
{
get
{
return ib_HeaderVisible;
}
set
{
ib_HeaderVisible = value;
}
}
/// <summary>
/// The Text that should appear in the header.
/// </summary>
public string HeaderText
{
get
{
return is_HeaderText;
}
set
{
is_HeaderText = value;
}
}
/// <summary>
/// A collection for Nearby Place objects.
/// </summary>
public ObservableCollection<GBSPlaceDetail> GBSPlaceDetails { get; private set; }
/// <summary>
/// Constructor for the Places View Model
/// </summary>
public PlacesVM()
{
this.GBSPlaceDetails = new ObservableCollection<GBSPlaceDetail>();
this.GBSPlaceDetails.Add(new GBSPlaceDetail { Title = "Place 1" });
this.GBSPlaceDetails.Add(new GBSPlaceDetail { Title = "Place 2" });
this.GBSPlaceDetails.Add(new GBSPlaceDetail { Title = "Place 3" });
this.GBSPlaceDetails.Add(new GBSPlaceDetail { Title = "Place 4" });
this.GBSPlaceDetails.Add(new GBSPlaceDetail { Title = "Place 5" });
this.GBSPlaceDetails.Add(new GBSPlaceDetail { Title = "Place 6" });
HeaderVisible = false;
HeaderText = "This is my header text.";
}
}
}
Upvotes: 0
Views: 2795
Reputation: 5370
I set header to be visible at the beginning so you can click on Settings text. Few changes required.
In xaml copied only top part with changes, the rest is the same
<ListView x:Name="lvPlaces"
VerticalOptions="StartAndExpand"
HorizontalOptions="StartAndExpand"
HasUnevenRows="True"
ItemsSource="{Binding GBSPlaceDetails}"
Header="{Binding .}">
<ListView.HeaderTemplate>
<DataTemplate>
<StackLayout Orientation="Vertical" IsVisible="{Binding HeaderVisible}">
<Label x:Name="lblHeaderText" Text="{Binding HeaderText}" TextColor="White" FontSize="Medium" FontAttributes="Bold" />
<Label x:Name="lblHeaderLink" Text="Click here to change your settings."
TextColor="Blue" FontSize="Medium" FontAttributes="Bold">
<Label.GestureRecognizers>
<TapGestureRecognizer Tapped="btnSettings_Clicked"/>
</Label.GestureRecognizers>
</Label>
</StackLayout>
</DataTemplate>
</ListView.HeaderTemplate>
In code MainPage:
public partial class MainPage : ContentPage
{
PlacesVM lobj_PlaceVM;
public HiddenHeaderPage()
{
InitializeComponent();
lobj_PlaceVM = new PlacesVM();
BindingContext = lobj_PlaceVM;
}
private void btnSettings_Clicked(object sender, EventArgs e)
{
lobj_PlaceVM.HeaderVisible = !lobj_PlaceVM.HeaderVisible;
}
}
In code of model:
public class PlacesVM : INotifyPropertyChanged
{
private bool ib_HeaderVisible = false;
private string is_HeaderText = "";
/// <summary>
/// Indicates if the header should be visible. This only happens when a query was performed using the values as specified in the settings and no locations
/// were returned.
/// </summary>
public bool HeaderVisible
{
get
{
return ib_HeaderVisible;
}
set
{
ib_HeaderVisible = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
/// <summary>
/// The Text that should appear in the header.
/// </summary>
public string HeaderText
{
get
{
return is_HeaderText;
}
set
{
is_HeaderText = value;
}
}
/// <summary>
/// A collection for Nearby Place objects.
/// </summary>
public ObservableCollection<GBSPlaceDetail> GBSPlaceDetails { get; private set; }
/// <summary>
/// Constructor for the Places View Model
/// </summary>
public PlacesVM()
{
this.GBSPlaceDetails = new ObservableCollection<GBSPlaceDetail>();
this.GBSPlaceDetails.Add(new GBSPlaceDetail { Title = "Place 1" });
this.GBSPlaceDetails.Add(new GBSPlaceDetail { Title = "Place 2" });
this.GBSPlaceDetails.Add(new GBSPlaceDetail { Title = "Place 3" });
this.GBSPlaceDetails.Add(new GBSPlaceDetail { Title = "Place 4" });
this.GBSPlaceDetails.Add(new GBSPlaceDetail { Title = "Place 5" });
this.GBSPlaceDetails.Add(new GBSPlaceDetail { Title = "Place 6" });
HeaderVisible = true;
HeaderText = "This is my header text.";
}
}
Upvotes: 1