TaskCompletionSource and dismiss causes that multiple custom alertdialogs aren't appearing - c#
I got a problem related with the TaskCompletionSource object and the Dismiss function of an alert. This problem does not appear within the IOS version of the application
When the application sends an notification, two alerts with working functionality will show up when the user activates the application:
Authentication
Filling in a value.
However, when I enter the application I only get to see the authentication(because this alert is called first within the app) and the second alert never shows up. I already tried to override the Dismiss function and set the TaskCompletionSource object result to null, but this causes the same alert to appear an X times before the application crashes. Is there a way to repeat the TaskCompletionSource object so that I can see all the alerts? Or what kind of modifications do I need to make on the Dismiss function so that the TaskCompletionSource is completed once all the alerts are shown?
Android Fragment Example code:
public static readonly int AlertWidth = Device.Idiom == TargetIdiom.Phone ? 270 : 320;
class AlertDialogFragment : DialogFragment
{
public string Title;
public string Body;
public View Content;
public List<AlertButton> Buttons;
public TaskCompletionSource<object> tsc;
public Dialog AndroidCustomAlert(Activity activ)
{
Android.Views.LayoutInflater inflater = Android.Views.LayoutInflater.From(activ);
Android.Views.View view = inflater.Inflate(Resource.Layout.AlertDialogLayout, null);
AlertDialog.Builder builder = new AlertDialog.Builder(activ);
builder.SetView(view);
Android.Widget.TextView title = view.FindViewById<Android.Widget.TextView>(Resource.Id.Login);
title.Text = Title;
Android.Widget.TextView body = view.FindViewById<Android.Widget.TextView>(Resource.Id.pincodeText);
body.Text = Body;
body.MovementMethod = new Android.Text.Method.ScrollingMovementMethod();
Android.Widget.EditText pincode = view.FindViewById<Android.Widget.EditText>(Resource.Id.pincodeEditText);
Android.Widget.Button btnPositive = view.FindViewById<Android.Widget.Button>(Resource.Id.btnLoginLL);
Android.Widget.Button btnNegative = view.FindViewById<Android.Widget.Button>(Resource.Id.btnClearLL);
Android.Widget.Button btnNeutral = view.FindViewById<Android.Widget.Button>(Resource.Id.btnNeutral);
if (Title.Contains("Time"))
{
Android.Views.View secondView = inflater.Inflate(Resource.Layout.TimePickerLayout, null);
builder.SetView(secondView);
btnPositive = secondView.FindViewById<Android.Widget.Button>(Resource.Id.btnLoginLL);
btnNegative = secondView.FindViewById<Android.Widget.Button>(Resource.Id.btnClearLL);
var tp = secondView.FindViewById<Android.Widget.TimePicker>(Resource.Id.timePicker1);
tp.SetIs24HourView((Java.Lang.Boolean)true);
//Positive button feedback
btnPositive.Text = Buttons.Last().Text;
btnPositive.Click += delegate
{
var car = (Xamarin.Forms.TimePicker)Content;
var ts = new TimeSpan(tp.Hour, tp.Minute, 0);
car.Time = ts;
CommandsForButtons(Buttons.Last());
};
//Negative button feedback
btnNegative.Text = Buttons.First().Text;
btnNegative.Click += delegate
{
CommandsForButtons(Buttons.First());
};
}
else if (Title.Contains("How are you"))
{
btnPositive.Visibility = Android.Views.ViewStates.Gone;
btnNegative.Visibility = Android.Views.ViewStates.Gone;
btnNeutral.Visibility = Android.Views.ViewStates.Visible;
pincode.Visibility = Android.Views.ViewStates.Gone;
var happySlider = view.FindViewById<Android.Widget.SeekBar>(Resource.Id.happinessSlider);
happySlider.SetProgress(5, false);
happySlider.Visibility = Android.Views.ViewStates.Visible;
btnNeutral.Text = Buttons.First().Text;
btnNeutral.Click += delegate
{
var car = (StackLayout)Content;
var layoutView = (Xamarin.Forms.AbsoluteLayout)car.Children[1];
var slider = (Slider)layoutView.Children[1];
var totalHappyValue = happySlider.Progress / 10;
slider.Value = totalHappyValue;
CommandsForButtons(Buttons.First());
};
}
else
{
//Checks if there are no buttons, and if there aren't any, creates a neutral one
if (Buttons == null || Buttons.Count == 0)
{
btnPositive.Visibility = Android.Views.ViewStates.Gone;
btnNegative.Visibility = Android.Views.ViewStates.Gone;
btnNeutral.Visibility = Android.Views.ViewStates.Visible;
pincode.Visibility = Android.Views.ViewStates.Gone;
Buttons = new List<AlertButton> {
new AlertButton {
Text = "Oké",
IsPreferred = true,
Action = () => false
}
};
btnNeutral.Text = Buttons.First().Text;
btnNeutral.Click += delegate
{
CommandsForButtons(Buttons.First());
};
}
if (Content == null)
{
pincode.Visibility = Android.Views.ViewStates.Gone;
}
//Positive button feedback
btnPositive.Text = Buttons.Last().Text;
btnPositive.Click += delegate
{
var test = (StackLayout)Content;
if (test != null)
{
var car = (Entry)test.Children[0];
car.Text = pincode.Text;
}
CommandsForButtons(Buttons.Last());
};
//Negative button feedback
btnNegative.Text = Buttons.First().Text;
btnNegative.Click += delegate
{
CommandsForButtons(Buttons.First());
};
}
return builder.Create();
}
public void CommandsForButtons(AlertButton button)
{
Func<Task> dismiss = null;
var command = new Command(async () =>
{
var ab = button;
var cont = true;
if (ab.Action != null)
cont = ab.Action();
if (ab.ActionAsync != null)
{
cont = cont && await ab.ActionAsync();
}
if (!cont)
{
await dismiss();
}
});
dismiss = async () =>
{
dismiss = async () => { };
await Task.Run(() =>
{
Dismiss();
tsc.SetResult(null);
});
Log.Debug("TSC", tsc.Task.Status.ToString());
};
command.Execute(this);
}
public override Dialog OnCreateDialog(Bundle savedInstanceState)
{
var test = AndroidCustomAlert(Activity);
test.SetCanceledOnTouchOutside(false);
return test;
}
public override void Dismiss()
{
base.Dismiss();
}
}
public async Task Show(string title, string body, View content, List<AlertButton> buttons)
{
var tcs = new TaskCompletionSource<object>();
var adf = new AlertDialogFragment
{
Title = title,
Body = body,
Content = content,
Buttons = buttons,
tsc = tcs
};
var FragmentManager = ((Activity)Forms.Context).FragmentManager;
FragmentTransaction ft = FragmentManager.BeginTransaction();
//Remove fragment else it will crash as it is already added to backstack
Fragment prev = FragmentManager.FindFragmentByTag("alert");
if (prev != null)
{
ft.Remove(prev);
}
ft.AddToBackStack(null);
adf.Show(ft, "alert");
await tcs.Task;
}
The methods:
await Authentication();
await UserCheck();
And the IOS code:
public static readonly int AlertWidth = Device.Idiom == TargetIdiom.Phone ? 270 : 320;
public async Task Show(string title, string body, View content, List<AlertButton> buttons)
{
if (buttons == null || buttons.Count == 0)
{
buttons = new List<AlertButton> {
new AlertButton {
Text = "Oké",
IsPreferred = true,
Action = () => false
}
};
}
Func<Task> dismiss = null;
var captionSize = (double)StyleKit.PhoneDarkLabelStyles.Caption.Setters.First(s => s.Property == Label.FontSizeProperty).Value;
var titleSize = (double)StyleKit.PhoneDarkLabelStyles.Title.Setters.First(s => s.Property == Label.FontSizeProperty).Value;
var top = new StackLayout {
Padding = new Thickness(15, 20, 15, 20),
Spacing = 3,
Children = {
new Label {
Text = title,
Style = StyleKit.PhoneDarkLabelStyles.Title,
FontSize = Math.Max(16, titleSize),
HorizontalTextAlignment = TextAlignment.Center
},
new Label {
Text = body,
Style = StyleKit.PhoneDarkLabelStyles.Body,
//FontSize = ,
FontSize = Math.Max(14, captionSize),
HorizontalTextAlignment = TextAlignment.Center
} ,
new ContentView {
Padding = new Thickness(0,5,0,-10),
VerticalOptions = LayoutOptions.EndAndExpand,
Content = content
}
}
};
var buttonViews = buttons.Select(ab => new Button {
FontSize = Math.Max(16, titleSize),
Text = ab.Text,
FontAttributes = ab.IsPreferred ? FontAttributes.Bold : FontAttributes.None,
TextColor = ab.IsDestructive ? Color.Red : Color.Default,
Command = new Command(async () => {
var cont = true;
if (ab.Action != null)
cont = ab.Action();
if (ab.ActionAsync != null)
cont = cont && await ab.ActionAsync();
if (!cont)
await dismiss();
})
}).ToList();
var grid = new Grid {
RowDefinitions = {
new RowDefinition { Height = GridLength.Auto },
new RowDefinition { Height = GridLength.Auto }
},
ColumnSpacing = 0,
RowSpacing = 0
};
buttons.ForEach(button => {
grid.ColumnDefinitions.Add(
new ColumnDefinition {
Width = AlertWidth / buttonViews.Count
}
);
});
for (int i = 0; i < buttonViews.Count; i++)
{
grid.Children.Add(new BorderView {
BorderColor = Color.FromRgba(0,0,0,0.2),
Thickness = new Thickness(0, 1, (i + 1 < buttonViews.Count) ? 1 : 0, 0)
}, i, 1);
grid.Children.Add(buttonViews[i], i, 1);
}
grid.Children.Add(top, 0, buttons.Count, 0, 1);
var box = new Frame {
WidthRequest = AlertWidth,
BackgroundColor = Color.FromRgba(1,1,1,0.96),
Padding = 0,
Content = grid
};
var outer = new AbsoluteLayout {
BackgroundColor = Color.FromRgba(0,0,0,0.65),
Opacity = 0,
Children = { box }
};
AbsoluteLayout.SetLayoutFlags(box, AbsoluteLayoutFlags.PositionProportional);
AbsoluteLayout.SetLayoutBounds(box,
new Rectangle(0.5, 0.5, AbsoluteLayout.AutoSize, AbsoluteLayout.AutoSize));
var page = new ContentPage {
Content = /* new ScrollView { Content = */ outer // }
};
var tcs = new TaskCompletionSource<object>();
var topVC = UIApplication.SharedApplication.KeyWindow.RootViewController;
while (topVC.PresentedViewController != null) {
topVC = topVC.PresentedViewController;
}
var vc = page.CreateViewController();
topVC.Add(vc.View);
var innerView = vc.View.Subviews[0].Subviews[0];
vc.View.RemoveFromSuperview();
dismiss = async () => {
dismiss = async () => {};
await outer.FadeTo(0, 50);
innerView.RemoveFromSuperview();
tcs.SetResult(null);
};
topVC.Add(innerView);
var kbh = new KeyboardHelper();
kbh.KeyboardChanged += async (sender, e) => {
await box.TranslateTo(0, e.Visible ? (-e.Height / 2f) : 0, 100, Easing.CubicInOut);
};
await outer.FadeTo(1, 100);
await tcs.Task;
}
This looks like an and/or problem between threading or simply not setting the task completion.
In the IOS version you have
dismiss = async () => {
dismiss = async () => {};
await outer.FadeTo(0, 50);
innerView.RemoveFromSuperview();
tcs.SetResult(null);
};
There is no matching tcs.SetResult(null); statement in the android version.
Also of note is the async invocation, as waiting to call SetResult will block the main thread without it.
Related
MVVM with dynamic the Michrochart-NugetPackage doesn't work
I want to add a dynamic micro chart to my application but it doesn't work. After a call from a method a value gets added and it makes a completely new micro chart for my chart to have the new values, but the change isn't visible in the app. So the old Values stayed and there is no new one. Thanks for helping me. WeightList = new List<float>(); WeightList.Add(0); WeightList.Add((float)74.3); entries = new ChartEntry[30]; SyncArray(); private void SyncArray() { if (WeightList.Count != entries.Length) { entries = new ChartEntry[WeightList.Count]; } for (int i = 0; i <= WeightList.Count - 1; i++) { if (i == WeightList.Count - 1 || i == 0) { entries[i] = new ChartEntry(WeightList[i]) { Label = "" + i, ValueLabel = "" + WeightList[i] }; } else { entries[i] = new ChartEntry(WeightList[i]) { Label = "" + i }; } } chart = new LineChart() { Entries = entries, BackgroundColor = SKColors.Transparent }; Chart = chart; } public LineChart Chart { get => chart; set => SetProperty(ref chart, value); } public float Weight { get => weight; set { weight = value; WeightList.Add(weight); SyncArray(); } }
Credits: #Jason What to change: private void SyncArray() { if (WeightList.Count != entries.Length) { entries = new ChartEntry[WeightList.Count]; } for (int i = 0; i <= WeightList.Count - 1; i++) { if (i == WeightList.Count - 1 || i == 0) { entries[i] = new ChartEntry(WeightList[i]) { Label = "" + i, ValueLabel = "" + WeightList[i] }; } else { entries[i] = new ChartEntry(WeightList[i]) { Label = "" + i }; } } Chart = new LineChart() { Entries = entries, BackgroundColor = SKColors.Transparent }; }
Place patterns on polyline in iOS using Xamarin.forms.maps
Im using xamarin.forms.maps and successfully getting the polyline but I want to get some patterns on it as here and not able to achieve it. Can anyone please help me in solving this issue and my code is as below : formsMap.DrawPolyLine = () => { if (nativeMaps == null) { nativeMaps = Control as MKMapView; } nativeMaps.OverlayRenderer = GetOverlayRenderer; CLLocationCoordinate2D[] coords = new CLLocationCoordinate2D[IOSMapViewModel.DeviceTrackData.Count]; int index = 0; foreach (var position in IOSMapViewModel.DeviceTrackData) { coords[index] = new CLLocationCoordinate2D(position.Latitude, position.Longitude); index++; } routeOverlay = MKGeodesicPolyline.FromCoordinates(coords); if (nativeMap.Overlays != null) nativeMaps.RemoveOverlays(nativeMap.Overlays); IMKOverlay overlay = routeOverlay; nativeMaps.AddOverlay(routeOverlay, MKOverlayLevel.AboveLabels); }; nativeMap.GetViewForAnnotation = GetViewForAnnotation; nativeMap.CalloutAccessoryControlTapped += OnCalloutAccessoryControlTapped; } } MKOverlayRenderer GetOverlayRenderer(MKMapView mapView, IMKOverlay overlayWrapper) { if (polylineRenderer == null && !Equals(overlayWrapper, null)) { var overlay = Runtime.GetNSObject(overlayWrapper.Handle) as IMKOverlay; Foundation.NSNumber[] dashValues = { 3, 6 }; polylineRenderer = new MKPolylineRenderer(overlay as MKGeodesicPolyline) { FillColor = UIColor.Orange, StrokeColor = UIColor.Orange, LineWidth = 3, Alpha = 1f, LineDashPattern = dashValues }; //polylineRenderer.CreatePath(); } return polylineRenderer; }
Delete annotations from the map
How could i delete annotations from the map after chosing the new one ? So let's say i have chosen pin on the X and Y coordinates and would like to move this pin to another place without adding the new one. Also simply map.RemoveAnnotations(); does not work. Here is a code which depends on it: map = new MKMapView(new CGRect(0, 74 + point * 13, UIScreen.MainScreen.Bounds.Width, (UIScreen.MainScreen.Bounds.Height - (74 + point * 20)))); map.UserInteractionEnabled = true; map.ZoomEnabled = true; map.ScrollEnabled = true; map.MapType = MKMapType.Standard; map.ShowsUserLocation = true; var longTap = new UILongPressGestureRecognizer() { }; longTap.AddTarget(() => AddPin(longTap, slider.Value)); longTap.MinimumPressDuration = 2.0; map.AddGestureRecognizer(longTap); map.GetViewForAnnotation += (mapView, annotation) => { anView = new MKAnnotationView(annotation, Resources.kClusterAnnotationId); anView.ClipsToBounds = true; anView.CanShowCallout = false; anView.Image = UIImage.FromFile("Icons/customMapPin.png"); return anView; }; private void AddPin(UILongPressGestureRecognizer longTap, float value) { if (ifPointExist == false) { ifPointExist = true; touchPoint = longTap.LocationInView(map); pinMapCords = this.map.ConvertPoint(touchPoint, map); CLLocation loc = new CLLocation(pinMapCords.Latitude, pinMapCords.Longitude); map.AddAnnotations(new MKPointAnnotation() { Coordinate = new CLLocationCoordinate2D(pinMapCords.Latitude, pinMapCords.Longitude) }); CLGeocoder geocoder = new CLGeocoder(); geocoder.ReverseGeocodeLocation(loc, (CLPlacemark[] placemarks, NSError error) => { str = placemarks[0].AddressDictionary; str.ToString(); }); AddCircle(value); MKCoordinateSpan span = new MKCoordinateSpan(0.10, 0.10); var coords = new CLLocationCoordinate2D(pinMapCords.Latitude, pinMapCords.Longitude); map.Region = new MKCoordinateRegion(coords, span); ifPointExist = false; } } Thanks in advance
Java.Lang.IllegalStateException: The content of the adapter has changed but ListView did not receive a notification (xamarin.forms)
I have bound one list from web service. First time only 5 items are loaded and then when user scroll the list view other 5 items are loaded. Every thing is working fine but I am facing issue in one scenario. First time when List is bound (don't do scrolling) and if immediately I clicked on some list item then "ItemTepped" event is fired and page should be navigated to other page but problem is it showing me error as below image. I have put Active indicator for loading. This code is in xamarin.forms (Portable library). This is not xamarin.Android project. public partial class NewsGalleryListPage : ContentPage { int totalItems = 0; decimal MaxIndex = 0; int index = 0; List<Newslist> NewsList; public NewsGalleryListPage() { InitializeComponent(); NewsGalleryLists.ItemTapped += NewsGalleryLists_ItemTapped; NewsGalleryLists.ItemAppearing += NewsGalleryLists_ItemAppearing1; loadingIndicator.IsVisible = true; loading.IsRunning = true; loading.IsVisible = true; CallWebServiceForNewsGalleryList(index); } private void NewsGalleryLists_ItemAppearing1(object sender, ItemVisibilityEventArgs e) { try { if (totalItems != 0) { MaxIndex = Math.Ceiling(((decimal)totalItems) / 5); if (index < MaxIndex) { if (NewsList != null && e.Item != null && e.Item == NewsList[NewsList.Count - 1]) { index++; if (index != MaxIndex) { loadingIndicator.IsVisible = true; loading.IsVisible = true; loading.IsRunning = true; CallWebServiceForNewsGalleryList(index); } } } } } catch(Exception ex) { } } private void NewsGalleryLists_ItemTapped(object sender, ItemTappedEventArgs e) { var selectedNewsGalleryListItem = sender as Xamarin.Forms.ListView; var obj = selectedNewsGalleryListItem.SelectedItem as CMO.ServicesClasses.Newslist; Navigation.PushAsync(new CMO.Gallery.NewsGalleryDetail(obj)); } public async void CallWebServiceForNewsGalleryList(int index) { try { string lang = "en"; if (Application.Current.Properties.ContainsKey("Language")) { lang = Application.Current.Properties["Language"] as string; // do something with i } List<KeyValuePair<string, string>> values = new List<KeyValuePair<string, string>>(); values.Add(new KeyValuePair<string, string>("lang",lang)); values.Add(new KeyValuePair<string, string>("title", "")); values.Add(new KeyValuePair<string, string>("index", Convert.ToString(index))); values.Add(new KeyValuePair<string, string>("limit", "5")); var response = await GeneralClass.GetResponse<CMO.ServicesClasses.RootObjectNewsGalleryList>("http://14.141.36.212/maharastracmo/api/getnewslist", values); if (response != null) { if (NewsList == null || index==0) { NewsList = new List<Newslist>(); } for(int i = 0; i < response.newslist.Count; i++) { var ObjectNewslist = new Newslist(); ObjectNewslist.page_id = response.newslist[i].page_id; ObjectNewslist.title = response.newslist[i].title; ObjectNewslist.date = response.newslist[i].date; ObjectNewslist.news_photo = response.newslist[i].news_photo; ObjectNewslist.content = response.newslist[i].content; NewsList.Add(ObjectNewslist); } totalItems = response.total_results; NewsGalleryLists.RowHeight = 100; var x = NewsGalleryLists.RowHeight; this.Title = AppResources.LNewsGallery; NewsGalleryLists.ItemsSource = NewsList; } } catch (WebException exception) { } loading.IsVisible = false; loading.IsRunning = false; loadingIndicator.IsVisible = false; } } I have gone through following link https://forums.xamarin.com/discussion/23124/proper-way-to-update-the-tableviews-sections-content https://forums.xamarin.com/discussion/21994/threading-in-xamarin-forms I have tried Xamarin.Forms.Device.BeginInvokeOnMainThread (() => {}); Task.Run(() => { }); I don't know how to handle thread in xamarin forms as beginner level.
It usually happens when you use TemplateSelector, but creating a new one for each row. Create one instance of TemplateSelector and use it.
How to check if checkbox is selected?
I have little issue with checkbox added programmatically. I don't know how to check which checkbox are selected, when I hit "Send Button". layout.RemoveAllViewsInLayout(); CheckBox _Options = new CheckBox(Activity); ScrollView _Scroll = new ScrollView(Activity); _Scroll.LayoutParameters = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WrapContent, ViewGroup.LayoutParams.WrapContent); LinearLayout _LScroll = new LinearLayout(Activity); _LScroll.LayoutParameters = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WrapContent, ViewGroup.LayoutParams.WrapContent); _LScroll.Orientation = Orientation.Vertical; _LScroll.SetGravity(GravityFlags.CenterHorizontal); //_Scroll.AddView(_LScroll); Button _Send = new Button(Activity); _Send.Text = "Wyślij"; _Send.LayoutParameters = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MatchParent, ViewGroup.LayoutParams.WrapContent); for (int i = 0; i < _Item.options.Length; i++) { _Options.Text = _Item.options[i]; _Options.Id = i; _Options.LayoutParameters = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MatchParent, ViewGroup.LayoutParams.WrapContent); _LScroll.AddView(_Options); } _Send.Click += delegate { _MultiAnswer._QuestionId = _Item.id; for(int i = 0; i < _Item.options.Length; i++) { if (_Options.Selected == true) { _MultiAnswer._AnwserOptionIds.SetValue(i + 1, i); } } output = JsonConvert.SerializeObject(_MultiAnswer); SendJson(_Url, DataCache._Login, output); SetLayout(layout, btn); }; _Scroll.AddView(_LScroll); layout.AddView(_Scroll); layout.AddView(_Send); I'll try to work on ID of checkbox, but I really don't know how to do it. I was thinking on method, which give me code which create checkbox, but still don't know how to check if checkbox is selected.
I understand that you've many checkbox controls. So add them to a list as follows: List<Checkbox> checkboxes = new List<Checkbox> { chk1, chk2, chk3 }; When you want to know which ones are checked, you'll do this: IEnumerable<Checkbox> checkedCheckboxes = checkboxes.Where(chk => chk.Checked);
This is a quick and dirty sample on how to generate dynamic cheboxes and retreive their state : public class MainActivity : Activity { public class MyItem { public string[] options { get; set; } public int id { get; set; } } public class MyMultiAnswer { public int _QuestionId { get; set; } } private List<CheckBox> _chkList = new List<CheckBox>(); protected override void OnCreate(Bundle bundle) { base.OnCreate(bundle); var _Item = new MyItem() { options =new string [] { "aaa", "bbb", "ccc" }, id=0 }; var _MultiAnswer = new MyMultiAnswer() { _QuestionId = 0 }; ScrollView _Scroll = new ScrollView(this); _Scroll.LayoutParameters = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WrapContent, ViewGroup.LayoutParams.WrapContent); LinearLayout _LScroll = new LinearLayout(this); _LScroll.LayoutParameters = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WrapContent, ViewGroup.LayoutParams.WrapContent); _LScroll.Orientation = Orientation.Vertical; _LScroll.SetGravity(GravityFlags.CenterHorizontal); TextView txView = new TextView(this); //_Scroll.AddView(_LScroll); Button _Send = new Button(this); _Send.Text = "test"; _Send.LayoutParameters = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MatchParent, ViewGroup.LayoutParams.WrapContent); for (int i = 0; i < _Item.options.Length; i++) { CheckBox _Options = new CheckBox(this); _chkList.Add(_Options); _Options.Text = _Item.options[i]; _Options.Id = i; _Options.LayoutParameters = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MatchParent, ViewGroup.LayoutParams.WrapContent); _LScroll.AddView(_Options); } _Send.Click += delegate { _MultiAnswer._QuestionId = _Item.id; string strChkIds = ""; foreach (var chk in _chkList.Where(c => c.Checked)) { //_MultiAnswer._AnwserOptionIds.SetValue(_Options.Id + 1, _Options.Id); //do something strChkIds += " - " + chk.Id; } // or for (int i = 0; i < _Item.options.Length; i++) { if (_chkList[i].Checked == true) { //_MultiAnswer._AnwserOptionIds.SetValue(i + 1, i); //do something } } //output = JsonConvert.SerializeObject(_MultiAnswer); //SendJson(_Url, DataCache._Login, output); //SetLayout(layout, btn); txView.Text = "selected ids " + strChkIds; }; _Scroll.AddView(_LScroll); _LScroll.AddView(_Send); _LScroll.AddView(txView); // Set our view from the "main" layout resource SetContentView(_Scroll); } } This is a sample about how you can achieve this in a minimum effort.