user3265665 user3265665 - 1 month ago 25
C# Question

How to call async method from not async method?

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.

Answer

Try following

protected Task 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));
                await CallWebService(StartDate.Month, StartDate.Year);
                //CallServiceInNewTask(StartDate.Month, StartDate.Year);
                //Device.BeginInvokeOnMainThread(() => await ChangeCalendar(CalandarChanges.All));

            }
            catch (Exception e)
            {

            }
        }

Your Webservice should be like

public async Task 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)
            {
               await ChangeCalendar(CalandarChanges.All);
            }
            else
            {
               await ChangeCalendar(CalandarChanges.StartDate);
            }
        }
        catch (WebException e)
        {

        }
    } 

And Your ChnageCalender method should be like

protected Task 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)
        {

        }
    }