Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Error: Only the original thread that created a view hierarchy can touch its views in Xamarin

I am getting an error error: Only the original thread that created a view hierarchy can touch its views

in line

BookingAdapter expListAdapter = new BookingAdapter (this, listDataHeader,  listDataChild);
try{
explistView.SetAdapter (expListAdapter);
explistView.SetGroupIndicator (null);
}
catch(Exception e) {
Toast.MakeText (this,e+"",ToastLength.Long).Show();
}

and here is my piece of code

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using System.ServiceModel.Web;
using SalonServices;
using System.ServiceModel;

namespace PariSalon
{
[Activity (Label = "BookingRequest")]           
public class BookingRequest : Activity
{
    public List<GetServices> listDataHeader;
    public List<GetServices> services;
    Dictionary<GetServices, List<String>> listDataChild;
    ExpandableListView explistView;
    public static readonly EndpointAddress EndPoint = new EndpointAddress("http://xxx.xxx.Xx.xx/SalonService/SalonServices.svc");
    //public static readonly EndpointAddress EndPoint = new EndpointAddress("http://xxxx");
    private SalonServicesClient serviceClient;

    protected override void OnCreate (Bundle bundle)
    {
        base.OnCreate (bundle);

        SetContentView(Resource.Layout.Booking_request);
        InitializeSalonServiceClient();
        Button submit = FindViewById<Button> (Resource.Id.button2);


        //string userid = "1";
        //serviceClient.GetServicesForUserAsync (userid);
        string userid = "1";
        serviceClient.GetServicesForUserAsync (userid);
        //serviceClient.GetServicesForUserAsync (userid);

        submit.Click += delegate {
            Intent intent = new Intent(this, typeof(Booking_Request_sent));
            StartActivity(intent);
        };


        // Create your application here
        /*          

        explistView.SetOnGroupClickListener( new OnGroupClickListener());

//Catch click event attempt 2
        explistView.GroupClick += (object pobjSender,   ExpandableListView.GroupClickEventArgs pArgs) =>
        {
            int len = expListAdapter.GroupCount;
            for(int i=0;i<len;i++)
            {

                if(i!=groupPosition)
                {
                    explistView.CollapseGroup(i);
                }
                if(i==groupPosition){
                    if(explistView.IsGroupExpanded(groupPosition)){
                        explistView.CollapseGroup(groupPosition);
                    }
                    else {
                        explistView.ExpandGroup(groupPosition);
                    }


                }
            }
        };*/
    }
    private void InitializeSalonServiceClient()
    {
        BasicHttpBinding binding = CreateBasicHttp();
        serviceClient = new SalonServicesClient(binding, EndPoint);
        //serviceClient.GetServicesForUserCompleted += GetServicesForUserCompleted;
        //serviceClient.GetProductDetailsCompleted += GetProductDetailsCompleted;
        serviceClient.GetServicesForUserCompleted += GetServicesForUserCompleted;

    }


    private void GetServicesForUserCompleted(object sender, GetServicesForUserCompletedEventArgs getServiceDataCompletedEventArgs)
    {
        string msg = null;

        if (getServiceDataCompletedEventArgs.Error != null)
        {
            msg = getServiceDataCompletedEventArgs.Error.Message;
        }
        else if (getServiceDataCompletedEventArgs.Cancelled)
        {
            msg = "Request was cancelled.";
        }
        else
        {
            services = new List<GetServices>(getServiceDataCompletedEventArgs.Result);
            prepareListData ();
            explistView = FindViewById<ExpandableListView> (Resource.Id.expandableselectservicetype);
            BookingAdapter expListAdapter = new BookingAdapter (this, listDataHeader, listDataChild);
            try{
                explistView.SetAdapter (expListAdapter);
                explistView.SetGroupIndicator (null);
            }
            catch(Exception e) {
                Toast.MakeText (this,e+"",ToastLength.Long).Show();
            }


        }

    }

    private static BasicHttpBinding CreateBasicHttp()
    {
        BasicHttpBinding binding = new BasicHttpBinding
        {
            Name = "basicHttpBinding",
            MaxBufferSize = 2147483647,
            MaxReceivedMessageSize = 2147483647
        };
        TimeSpan timeout = new TimeSpan(0, 0, 50);
        binding.SendTimeout = timeout;
        binding.OpenTimeout = timeout;
        binding.ReceiveTimeout = timeout;
        return binding;
    }


    private void prepareListData() {
        listDataHeader = new List<GetServices>();
        listDataChild = new Dictionary<GetServices, List<String>>();
        listDataHeader.Clear ();
        if (services != null) {
            foreach (GetServices pd in services) {
                listDataHeader.Add (pd);
            }
            // Adding child data
            //listDataHeader.Add("Top 250/n");
            //listDataHeader.Add("Now Showing");
            //listDataHeader.Add("Coming Soon..");      

            List<String> childLabel = new List<String> ();
            childLabel.Add ("Date :");
            childLabel.Add ("Time :");
            childLabel.Add ("User :");
            childLabel.Add ("Second User:");
            childLabel.Add ("Status :");
            childLabel.Add ("Cancel ");

            listDataChild.Add (listDataHeader.ElementAt (0), childLabel); // Header, Child data
            listDataChild.Add (listDataHeader.ElementAt (1), childLabel);
            listDataChild.Add (listDataHeader.ElementAt (2), childLabel);
        }
    }


}
}

I have another adapter class but I think the error is only in this class. How can I solve this problem. Can any one please help me to solve this problem.

like image 236
suraj shukla Avatar asked Jan 16 '14 12:01

suraj shukla


2 Answers

The linked article in the accepted answer talks about InvokeOnMainThread which is an IOS thing. No idea why it was accepted as an answer for Android as the question is tagged.

For Android you use Activity.RunOnUiThread. Relevant documentation is here: http://developer.xamarin.com/guides/android/advanced_topics/writing_responsive_applications/

Because you are rigging this up from somewhere that inherits from Activity you can just wrap the relevant code so this:

BookingAdapter expListAdapter = new BookingAdapter (this, listDataHeader,  listDataChild);
try{
    explistView.SetAdapter (expListAdapter);
    explistView.SetGroupIndicator (null);
}
catch(Exception e) {
    Toast.MakeText (this,e+"",ToastLength.Long).Show();   
}

becomes:

RunOnUiThread(() =>
{
    BookingAdapter expListAdapter = new BookingAdapter (this, listDataHeader,  listDataChild);
    try{
        explistView.SetAdapter (expListAdapter);
        explistView.SetGroupIndicator (null);
    }
    catch(Exception e) {
        Toast.MakeText (this,e+"",ToastLength.Long).Show();   
    }
});

That's really all there is to it.

like image 66
nathanchere Avatar answered Nov 15 '22 00:11

nathanchere


Here is a cross platform solution in xamarin for this issue;

 Device.BeginInvokeOnMainThread(() =>
 {
   //Your code here
 });
like image 26
Asım Gündüz Avatar answered Nov 14 '22 23:11

Asım Gündüz