Forum Xamarin.Forms
We are excited to announce that the Xamarin Forums are moving to the new Microsoft Q&A experience. Q&A is the home for technical questions and answers at across all products at Microsoft now including Xamarin!

We encourage you to head over to Microsoft Q&A for .NET for posting new questions and get involved today.

how to access a control from an object method?

Andre_S_CAndre_S_C Member ✭✭
edited September 16 in Xamarin.Forms

I'm about to badly embarrass my self here - being a complete newb to c# (& OO) and Xamarin.Forms (trying to learn too much in one go, I know)
I'm trying to create a stack-layout of options that will contain e.g. labels and buttons in which I want to control the Text property of the buttons when any of them are clicked.

I previously tried using databinding/itemsource on the stacklayout but got even more lost and have not been able to find examples I could make very much sense of - the documentation looks like it should be really simple, alas :-(

In the code listed below I can access both the mapOptsCntrl object and its methods as well as the stack layout control via its x:Name from the event handler methods of buttons in the XAML. But if I want to change things based on programmatically created button having been clicked I'm kinda lost.

I hope this is not too much code to post here:
`
using System;
using System.Collections.Generic;
using System.Linq;
using Xamarin.Forms;

namespace AgentApp
{
public partial class zDev_Map_Options_list : ContentPage
{

    public class LocOption : Object
    {
        public string AddressLine { get; set; }
        public string State { get; set; }
    }

    public class MapOptsCntrl : Object
    {
        public Dictionary<string, LocOption> ListOptsContainer = new Dictionary<string, LocOption>();

        public void Create(int number)
        {
            for (int i = 0; i < number; i++)
            {
                string key = i.ToString();
                LocOption LocOption = new LocOption { AddressLine = "Addy str " + key, State = "Show", };
                ListOptsContainer.Add(key, LocOption);
            }
        }
        public List<StackLayout> Draw()
        {
            int optsCount = ListOptsContainer.Count();
            List<StackLayout> listItems = new List<StackLayout>();
            for (int i = 0; i < optsCount; i++)
            {
                string key = i.ToString();
                Button listOptBtn = new Button { Text = ListOptsContainer[key].State + " " + key, };
                listOptBtn.Clicked += (sender, args) => { this.Click(key); };
                StackLayout listItem = new StackLayout
                {
                    Orientation = StackOrientation.Horizontal,
                    Children = { new Label { Text = "Label " + key }, listOptBtn, },
                };
                listItems.Add(listItem);
            };
            return listItems;
        }
        public void Click(string key)
        {
            Console.WriteLine("Click " + key + " state is " + ListOptsContainer[key].State);
            int optsCount = ListOptsContainer.Count();
            for (int i = 0; i < optsCount; i++)
            {
                string newState;
                string thisKey = i.ToString();
                if (i.ToString() == key)
                {
                    string curState = ListOptsContainer[key].State;
                    newState = (curState == "Use") ? "Show" : "Use";
                }
                else { newState = "Show"; }
                ListOptsContainer[thisKey].State = newState;

            }
            //  how to trigger a redraw?
            //// to efectively do what btn_redraw_Clicked does?
        }
    }

    MapOptsCntrl mapOptsCntrl = new MapOptsCntrl();
    public zDev_Map_Options_list()
    {
        InitializeComponent();
    }

    private void btn_go_Clicked(object sender, EventArgs e)
    {
        mapOptsCntrl.Create(3);
        List<StackLayout> listItems = mapOptsCntrl.Draw();
        OptionsListStack.Children.Clear();
        foreach (StackLayout item in listItems)
        {
            OptionsListStack.Children.Add(item);
        }
    }
    private void btn_redraw_Clicked(object sender, EventArgs e)
    {
        List<StackLayout> listItems = mapOptsCntrl.Draw();
        OptionsListStack.Children.Clear();
        foreach (StackLayout item in listItems)
        {
            OptionsListStack.Children.Add(item);
        }
    }
}

}
`

and the xaml:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             mc:Ignorable="d"
             x:Class="AgentApp.zDev_Map_Options_list">
    <ContentPage.Content>
        <Grid RowDefinitions="*,*,*,5*" x:Name="mainGrid">
            <Label Text="Map Options List Event Handeling" Grid.Row="0" HorizontalOptions="CenterAndExpand" />

            <Button x:Name="btn_go" Text="Create"  Grid.Row="1" Clicked="btn_go_Clicked"/>
            <Button x:Name="btn_redraw" Text="Redraw"  Grid.Row="2" Clicked="btn_redraw_Clicked"/>

            <StackLayout x:Name="OptionsListStack" Grid.Row="3"/>
        </Grid>
    </ContentPage.Content>
</ContentPage>

Thanks in advance for any direction or help!

Best Answers

  • LandLuLandLu Member, Xamarin Team Xamurai
    Accepted Answer

    would you recommend going (or attempting) the MVVM route?

    Yes, you could have a try.

Answers

  • Andre_S_CAndre_S_C Member ✭✭

    Awesome, thank you so much!

    However, I highly recommend you to use a listview to display a set of data with the same template:

    ...
    would you recommend going (or attempting) the MVVM route?

  • LandLuLandLu Member, Xamarin Team Xamurai
    Accepted Answer

    would you recommend going (or attempting) the MVVM route?

    Yes, you could have a try.

Sign In or Register to comment.