I am creating a cross-platform app using Xamarin Forms 4.1 in VS 2019.
I need a slide up menu who's menu options change depending on the tapped cell date in a calendar selection. I've installed SlideOverKit to attempt to accomplish this. Getting the menu itself works, but changing the options dynamically isn't working.
How should I proceed?
As I said, I've tried passing in the dates, but I also tried saving the date to SecureStorage and requesting the string in the SlideUpMenu's loading method... I believe I may be hitting a 'life cycle of a view' issue.
Here, I pass the selected date from the content page to the slide menu view and a model containing data.
public partial class PublicCalendarPage : MenuContainerPage
{
private CalendarModel _calendarModel;
private bool _showDetails = true;
public PublicCalendarPage(CalendarModel calendarModel)
{
InitializeComponent();
Content.BackgroundColor = Color.White;
BindingContext = new PublicCalendarViewModel(this, new ApiService())
{
CalendarModel = GetCalendarModel(calendarModel)
};
_calendarModel = calendarModel;
SlideMenu = new ShowMealsView(new DateTime(), calendarModel.CalendarDays);
}
private CalendarModel GetCalendarModel(CalendarModel calendarModel)
{
//gets the model data via api call
}
private void Schedule_OnCellTapped(object sender, CellTappedEventArgs e)
{
SlideMenu = new ShowMealsView(e.Datetime, _calendarModel.CalendarDays);
ShowMenu();
}
}
Below is the code behind for loading the menu
public partial class ShowMealsView : SlideMenuView
{
private readonly List<CalendarDayModel> _calendarDays;
public ShowMealsView(DateTime eDatetime, List<CalendarDayModel> calendarDaysList)
{
InitializeComponent();
HeightRequest = 80;
IsFullScreen = true;
MenuOrientations = MenuOrientation.BottomToTop;
BackgroundColor = Color.LightGray;
BackgroundViewColor = Color.Transparent;
_calendarDays = calendarDaysList;
if (Device.RuntimePlatform == Device.Android)
this.HeightRequest += 50;
var layout = GetLayout(eDatetime);
Content = layout;
}
private Grid GetLayout(DateTime date)
{
var layout = new Grid();
// formats grid layout before the relevant code
var dinnerGrid = new Grid();
dinnerGrid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) });
dinnerGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(10, GridUnitType.Absolute) });
dinnerGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
var dinnerBox = new BoxView
{
VerticalOptions = LayoutOptions.Fill,
BackgroundColor = Color.FromHex("#f3d176")
};
dinnerGrid.Children.Add(dinnerBox, 0, 0);
//var selectedDate = SecureStorage.GetAsync("SelectedDate").Result;
var selectedDateTime = date;
var dinnerLabel = new Label
{
Text = "Provide Dinner",
TextColor = Color.Black,
HorizontalOptions = LayoutOptions.Center,
HorizontalTextAlignment = TextAlignment.Center,
VerticalTextAlignment = TextAlignment.Center,
VerticalOptions = LayoutOptions.Center
};
if (_calendarDays.Any(x => x.ForDay == selectedDateTime.Date && x.Email != null))
{
dinnerLabel = new Label
{
Text = $"A DINNER EXISTS!",
TextColor = Color.Black,
HorizontalOptions = LayoutOptions.Center,
HorizontalTextAlignment = TextAlignment.Center,
VerticalTextAlignment = TextAlignment.Center,
VerticalOptions = LayoutOptions.Center
};
}
dinnerGrid.Children.Add(dinnerLabel, 1, 0);
var table = new TableView
{
Root = new TableRoot { new TableSection { new ViewCell() { View = lunchGrid }, new ViewCell() { View = dinnerGrid } } },
Intent = TableIntent.Data
};
layout.Children.Add(table, 0, 0);
return layout;
}
}
Initial loading returns "Provide Dinner"
Once a selected date is made on the content page, the menu selection should include "A DINNER EXISTS!"
However, even though a debug shows that dinnerLabel.Text might equal "A Dinner EXISTS", what is actually showing on screen is always "Provide Dinner"
UPDATE:
I've switched to using ObservableCollection, using that collection as a ListView itemsource because I keep reading that ListView automatically updates its views depending on what data is in the list. (if anything is added or removed)
This does not work, but I'm willing admit I may be doing it wrong as I've never used ListViews...
Essentially I'm still getting ONLY original state of the view which only shows "Provide Dinner"; and again when debugging the property assigned in the model does have the value "A Dinner Exists!" ... so getting the same result with this different method
ANOTHER UPDATE:
I've also tried replacing the GetGridLayout method with adding some XAML, and setting the itemsource in the constructror, then adding a new method like
private void GetCollection(DateTime eDatetime)
{
_myCollection.Clear();
var lunch = new CollectionListItem { Words = "Provide Lunch" };
_myCollection.Add(lunch);
if (_calendarDays.Any(x => x.ForDay == eDatetime.Date && x.Email != null))
{
_myCollection.Add(new CollectionListItem { Words = $"Dinner: {eDatetime}" });
}
else
{
var dinner = new CollectionListItem { Words = "Provide Dinner" };
_myCollection.Add(dinner);
}
BottomListView.ItemsSource = null;
BottomListView.ItemsSource = _myCollection;