I am working in xamarin forms. I am trying to bind Web service in calender control. refer following link for calendar control (XamForms.Controls.Calendar).
https://github.com/rebeccaXam/XamForms.Controls.Calendar
First Function is to Create 7*6=42 labels and buttons then "callWebService" method to call service function which is async method to get response from service.
protected void FillCalendarWindows()
{
try
{
for (int r = 0; r < 6; r++)
{
for (int c = 0; c < 7; c++)
{
if (r == 0)
{
labels.Add(new Label
{
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.Center,
TextColor = Color.Black,
FontSize = 18,
FontAttributes = FontAttributes.Bold
});
DayLabels.Children.Add(labels.Last(), c, r);
}
buttons.Add(new CalendarButton
{
BorderRadius = 0,
BorderWidth = BorderWidth,
BorderColor = BorderColor,
FontSize = DatesFontSize,
BackgroundColor = DatesBackgroundColor,
HorizontalOptions = LayoutOptions.FillAndExpand,
VerticalOptions = LayoutOptions.FillAndExpand
});
buttons.Last().Clicked += DateClickedEvent;
MainCalendar.Children.Add(buttons.Last(), c, r);
}
}
flag = 1;
//Device.BeginInvokeOnMainThread(() => CallWebService(StartDate.Month, StartDate.Year));
CallWebService(StartDate.Month, StartDate.Year);
//CallServiceInNewTask(StartDate.Month, StartDate.Year);
//Device.BeginInvokeOnMainThread(() => ChangeCalendar(CalandarChanges.All));
}
catch (Exception e)
{
}
}
Second Function is to "callWebService" function where I collect response in list collection object then call "ChangeClaendar" function which is used to bind labels and button text and fill appropriate color.
public async void CallWebService(int Month, int Year)
{
try
{
var response = await GetResponseFromWebService.GetResponse<ServiceClasses.RootObject_AttendanceTable>(ServiceURL.GetAttendanceTableList + "Month=" + Month + "&Year=" + Year + "&EmpCd=" + _empCode);
if (response.Flag == true)
{
if (ListObjAttendanceTblList == null)
{
ListObjAttendanceTblList = new List<LstAttendanceDtl>();
}
for (int i = 0; i < response.lstAttendanceDtl.Count; i++)
{
var objAttendanceTableList = new LstAttendanceDtl();
objAttendanceTableList.AttendanceDt = response.lstAttendanceDtl[i].AttendanceDt;
objAttendanceTableList.EarlyDeparture = response.lstAttendanceDtl[i].EarlyDeparture;
objAttendanceTableList.InTime = response.lstAttendanceDtl[i].EarlyDeparture;
objAttendanceTableList.LateArrival = response.lstAttendanceDtl[i].EarlyDeparture;
objAttendanceTableList.OutTime = response.lstAttendanceDtl[i].OutTime;
objAttendanceTableList.OverTime = response.lstAttendanceDtl[i].OverTime;
objAttendanceTableList.Reason = response.lstAttendanceDtl[i].Reason;
objAttendanceTableList.Remark = response.lstAttendanceDtl[i].Remark;
objAttendanceTableList.Shift = response.lstAttendanceDtl[i].Shift;
objAttendanceTableList.WorkingHrs = response.lstAttendanceDtl[i].WorkingHrs;
ListObjAttendanceTblList.Add(objAttendanceTableList);
}
}
else
{
}
if (flag == 1)
{
ChangeCalendar(CalandarChanges.All);
}
else
{
ChangeCalendar(CalandarChanges.StartDate);
}
}
catch (WebException e)
{
}
}
Third function is to "ChangeCalendar"
protected void ChangeCalendar(CalandarChanges changes)
{
try
{
if (changes.HasFlag(CalandarChanges.StartDate))
{
Device.BeginInvokeOnMainThread(() => CenterLabel.Text = StartDate.ToString(TitleLabelFormat));
}
var start = CalendarStartDate;
var beginOfMonth = false;
var endOfMonth = false;
for (int i = 0; i < buttons.Count; i++)
{
endOfMonth |= beginOfMonth && start.Day == 1;
beginOfMonth |= start.Day == 1;
LstAttendanceDtl objAttendanceDtl = ListObjAttendanceTblList.Find(s => s.AttendanceDt.Equals(start.Date.ToString("dd/MM/yyyy")));
string remarks = string.Empty;
if (i < 7 && WeekdaysShow && changes.HasFlag(CalandarChanges.StartDay))
{
Device.BeginInvokeOnMainThread(() => labels[i].Text = start.ToString(WeekdaysFormat));
//labels[i].Text = start.ToString(WeekdaysFormat);
//DateTime d = Convert.ToDateTime(objAttendanceDtl.AttendanceDt).Date;
}
if (changes.HasFlag(CalandarChanges.All))
{
Device.BeginInvokeOnMainThread(()=>buttons[i].Text = string.Format("{0}", start.Day));
//buttons[i].Text = string.Format("{0}", start.Day);
}
else
{
Device.BeginInvokeOnMainThread(() => buttons[i].TextWithoutMeasure = string.Format("{0}", start.Day));
}
buttons[i].Date = start;
var isInsideMonth = beginOfMonth && !endOfMonth;
if (objAttendanceDtl != null)
{
remarks = objAttendanceDtl.Remark;
if ((remarks.ToLower()).Trim() == stringFullDay.ToLower().Trim())
{
SetButtonPresent(buttons[i], isInsideMonth);
}
else if (remarks.ToLower().Trim() == stringAbsent.ToLower().Trim())
{
SetButtonAbsent(buttons[i], isInsideMonth);
}
else if (remarks.ToLower().Trim() == stringWeekOff.ToLower().Trim())
{
SetButtonWeekendMood(buttons[i], isInsideMonth);
}
else if (remarks.ToLower().Trim() == stringHolidays.ToLower().Trim())
{
SetButtonHolidays(buttons[i], isInsideMonth);
}
else if (remarks.ToLower().Trim() == stringSecondhalfAbsent.ToLower().Trim() ||
remarks.ToLower().Trim() == stringFirsthalfAbsent.ToLower().Trim())
{
SetButtonHalfDayMood(buttons[i], isInsideMonth);
}
else
{
SetButtonDisabled(buttons[i]);
}
}
else
{
SetButtonOutSideMonth(buttons[i]);
}
SpecialDate sd = null;
if (SpecialDates != null)
{
sd = SpecialDates.FirstOrDefault(s => s.Date.Date == start.Date);
}
if (sd != null)
{
SetButtonSpecial(buttons[i], sd);
}
else if (SelectedDate.HasValue && start.Date == SelectedDate.Value.Date)
{
SetButtonSelected(buttons[i], isInsideMonth);
}
start = start.AddDays(1);
}
}
catch (Exception e)
{
}
}
Problems are :
1. In "Changecalendar" function when I try to fill list of labels directly
labels[i].Text = start.ToString(WeekdaysFormat);
it showing me an error
"UIKit Consistency error: you are calling a UIKit method that can only be invoked from the UI thread." So to remove this error I wrote
Device.BeginInvokeOnMainThread(() => labels[i].Text = start.ToString(WeekdaysFormat));
Device.BeginInvokeOnMainThread(()=>buttons[i].Text = string.Format("{0}", start.Day));
Device.BeginInvokeOnMainThread(() => buttons[i].TextWithoutMeasure = string.Format("{0}", start.Day));
but it showing me an error
System.ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection.
2. if I put both function "CallWebService" and "ChangeCalendar" in "FillCalendarWindow" one after one then list object is not bound and control is come out of the function and directly ChangeCalendar function call and giving me null reference object.