Forum Xamarin.Forms

Announcement:

The Xamarin Forums have officially moved to the new Microsoft Q&A experience. Microsoft Q&A is the home for technical questions and answers at across all products at Microsoft now including Xamarin!

To create new threads and ask questions head over to Microsoft Q&A for .NET and get involved today.

Alternative way to get variable in code behind without x:Name

jenova1628jenova1628 Member ✭✭✭

Hi All,

Quick question I know it might sound stupid but I've been creating XAML pages a lot but now I want to try to approach it from using a JSON data to create a form based layout. So I have created a JSON and its classes and populated it with dummy data. the JSON has load of questions and a field to determine what the control will be (Entry, Datepicker, Picker, Editor etc etc.) I create the layout on load but when i create a button at the bottom to send that data back into a JSON object to upload to an API I am not sure how to get that form data back as you cant set the x:Name property in code behind and in my save function it can't see the control variable. I hope this makes sense and below is my code i use to bring back the form layout.

`public void LoadFormTemplate()
    {
        var generate = new CreateDummyData().CreateTestData();

        var ParentLayout = new StackLayout();
        foreach (Questions q in generate.Questions)
        {
            if (q.QuestionType == "Entry")
            {
                var ChildLayout = new Grid();

                ChildLayout.Padding = new Thickness(20);

                ChildLayout.ColumnDefinitions.Add(new ColumnDefinition());
                ChildLayout.ColumnDefinitions.Add(new ColumnDefinition());
                ChildLayout.RowDefinitions.Add(new RowDefinition());

                Label label = new Label { Text = q.QuestionName };
                Entry entry = new Entry { StyleId = "Question1Entry" };

                Grid.SetRow(label, 0);
                Grid.SetRow(entry, 0);
                Grid.SetColumn(label, 0);
                Grid.SetColumn(entry, 1);

                ChildLayout.Children.Add(label);
                ChildLayout.Children.Add(entry);

                ParentLayout.Children.Add(ChildLayout);
            }
            else if (q.QuestionType == "Picker")
            {

                var ChildLayout = new Grid();
                ChildLayout.Padding = new Thickness(20);

                ChildLayout.ColumnDefinitions.Add(new ColumnDefinition());
                ChildLayout.ColumnDefinitions.Add(new ColumnDefinition());
                ChildLayout.RowDefinitions.Add(new RowDefinition());

                Label label = new Label { Text = q.QuestionName };
                Picker entry = new Picker();

                foreach (Fields f in q.Fields)
                {
                    entry.Items.Add(f.Field);
                }

                entry.Title = "Please Select";

                Grid.SetRow(label, 0);
                Grid.SetRow(entry, 0);
                Grid.SetColumn(label, 0);
                Grid.SetColumn(entry, 1);

                ChildLayout.Children.Add(label);
                ChildLayout.Children.Add(entry);
                ParentLayout.Children.Add(ChildLayout);

            }
            else if (q.QuestionType == "DatePicker")
            {
                var ChildLayout = new Grid();
                ChildLayout.Padding = new Thickness(20);

                ChildLayout.ColumnDefinitions.Add(new ColumnDefinition());
                ChildLayout.ColumnDefinitions.Add(new ColumnDefinition());
                ChildLayout.RowDefinitions.Add(new RowDefinition());

                Label label = new Label { Text = q.QuestionName };
                DatePicker entry = new DatePicker { };

                Grid.SetRow(label, 0);
                Grid.SetRow(entry, 0);
                Grid.SetColumn(label, 0);
                Grid.SetColumn(entry, 1);

                ChildLayout.Children.Add(label);
                ChildLayout.Children.Add(entry);

                ParentLayout.Children.Add(ChildLayout);

            }
            else if (q.QuestionType == "Editor")
            {
                var ChildLayout = new Grid();
                ChildLayout.Padding = new Thickness(20);

                ChildLayout.ColumnDefinitions.Add(new ColumnDefinition());
                ChildLayout.RowDefinitions.Add(new RowDefinition());
                ChildLayout.RowDefinitions.Add(new RowDefinition());

                Label label = new Label { Text = q.QuestionName };
                Editor entry = new Editor { HeightRequest = 100 };

                Grid.SetRow(label, 0);
                Grid.SetRow(entry, 1);
                Grid.SetColumn(label, 0);
                Grid.SetColumn(entry, 0);
                entry.StyleId = "Editorquestion";

                ChildLayout.Children.Add(label);
                ChildLayout.Children.Add(entry);
                ParentLayout.Children.Add(ChildLayout);
            }
            this.Content = ParentLayout;
        }

        var submit = new Button { Text = "Submit Vehicle Check" };

        ParentLayout.Children.Add(submit);

        submit.Clicked += SaveJson;
    }

    private async void SaveJson(object sender, EventArgs e)
    {
       var result = await DisplayAlert("Farmer","Are you sure you want to submit the vehicle check","Yes","No");

        if (result)
        {

        }
    }`
Tagged:

Answers

  • AdamMeaneyAdamMeaney USMember ✭✭✭✭✭

    My best suggestion is to create the response object in the LoadFormTemplate, set it as the BindingContext of your ParentLayout, and bind all the things in the generated view to it.

    Then when you submit, it just says

    var button = sender as Button;
    MethodThatDoesHttpRequestAndNeedsSubmitObject.Call(button.BindingContext as SubmitObject);
    
  • jenova1628jenova1628 Member ✭✭✭

    @AdamMeaney thanks for the reply really appreciate it, could you explain about the response object and how to actually set it as a binding context. Are you saying if I set the parent layout to a binding context of a ViewModel it would return everything in the view? do you have some example code.

  • AdamMeaneyAdamMeaney USMember ✭✭✭✭✭

    Not exactly.

    The important parts of the following code are setting the bindings and binding contexts of the views appropriately.

    I only did this for one of them, as it's an example, but you should be able to get the idea.

            public TestPage()
            {
                var generate = new YourGeneratedThing();
                var response = new ObjectYouSendToServerWhenDone();
    
                var ParentLayout = new StackLayout()
                {
                    BindingContext = response
                };
                foreach (Questions q in generate.Questions)
                {
                    if (q.QuestionType == "Entry")
                    {
                        var ChildLayout = new Grid();
    
                        ChildLayout.Padding = new Thickness(20);
    
                        ChildLayout.ColumnDefinitions.Add(new ColumnDefinition());
                        ChildLayout.ColumnDefinitions.Add(new ColumnDefinition());
                        ChildLayout.RowDefinitions.Add(new RowDefinition());
    
                        Label label = new Label { Text = q.QuestionName };
                        Entry entry = new Entry { StyleId = "Question1Entry" };
    
                        Grid.SetRow(label, 0);
                        Grid.SetRow(entry, 0);
                        Grid.SetColumn(label, 0);
                        Grid.SetColumn(entry, 1);
    
                        ChildLayout.Children.Add(label);
                        ChildLayout.Children.Add(entry);
    
                        var questionResponse = new QuestionResponse();
                        entry.BindingContext = questionResponse;
                        entry.SetBinding(Entry.TextProperty, nameof(questionResponse.WhateverPropertyIsNamed), BindingMode.TwoWay);
    
                        response.Questions.Add(questionResponse);
    
                        ParentLayout.Children.Add(ChildLayout);
                    }
                    this.Content = ParentLayout;
                }
    
                var submit = new Button { Text = "Submit Vehicle Check" };
    
                ParentLayout.Children.Add(submit);
    
                submit.Clicked += SaveJson;
            }
    
            private void SaveJson(object sender, EventArgs e)
            {
                var button = sender as Button;
                var response = button.BindingContext as ObjectYouSendToServerWhenDone;
    
                // response.Questions has a Question object with the data from the entry on it now.
                SendToServer(response);
            }
    
Sign In or Register to comment.