Forum Xamarin.Android

Unique ID for programmatically created controls

Hi All

I am programmatically creating controls on the screen. If I create a control in XML I can assign the ID as such

android:id="@+id/btnAddTask"

When I do it in code I only have the option to set an integer.

Button btnAddTask = new Button (this);
btnAddTask.Id = 5;

The problem comes if I have two controls with the same ID. So is there a way of generating an ID which is not being used by a different control.

Cheers

Posts

  • CortezCortez USMember ✭✭✭

    You create your controls from code. Fine. But why do you want to use an ID for every controls? The reference can identify the control. In your code you create a button. With the btnAddTask you use it. Or you need a unique ID? Create a class for it. It should contain a list of views. You can add "controls" in it: TextViews, Buttons, CheckBoxes. etc. You can create a method which give you a unique id, for example the index in the list. You want to create a button with ID 5. Then your class take this Button in the list as fifth element. After you can get this item by using the GetViewById method or what you want. But i think the reference is enough to identify your "control". Just don't override it with another initializing.

  • CheesebaronCheesebaron DKInsider, University mod

    You can create an ids.xml file in Resources/Values/ where you can make some ID's which are not assigned to anything.

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <item name="my_id_1" type="id"/>
        <item name="my_id_2" type="id"/>
        <item name="my_id_3" type="id"/>
    </resources>
    

    Which then are accessible in Resource.Id.my_id_1, Resource.Id.my_id_2 etc.

  • SKallSKall USMember ✭✭✭✭

    A few ways I can think of but here is a simple one.

    Declare a static Queue with a Range of Id's somewhere in your application:

    public static readonly Queue<int> Queue = new Queue<int>(Enumerable.Range(10, 100));

    Assign the id at runtime by dequeue'ing the Id (removes it also from available Id's).

    btnAddTask.Id = Queue.Dequeue();

    If you are worrying about running out of Id's you would need to push back the id whenever the Button goes out of scope.

    Queue.Enqueue(btnAddTask.Id);

  • CortezCortez USMember ✭✭✭

    @Cheesebaron
    I am just interested in this kind of resources. What is the positive effect of this kind of ID storing in Values folder? When i think about the Values folder i can just think about the languages. For example the String.xml. You can store your strings in the resource and use it in the code. With another language specific language folders (Values-EN, Values-DE, Values-HU) you can handle very simple the languages. You just give the Values/Strings.xml file to someone who can translate the expressions to another languages. When he gives back you can copy this Values folder with another language ID, and you can override the Strings.xml file. Now you will support another languages. Very clever idea. But what is the situation with the IDs? You use this IDs in the code(set it in the xml and use it from code). Why it is a good idea too store it in a resource file? Documentation for example?

  • CheesebaronCheesebaron DKInsider, University mod

    The reason as to why having the id's in the Resources is that it will generate and ID that will not clash with an ID that might already be used in a View. That is basically it.

  • CortezCortez USMember ✭✭✭

    These IDs are generated automatically? Ok i understand the main reason. You cannot duplicate the IDs. But i dont know how can i use it. First you create the layout i think. You set the android:id="" and somehow you said to the compiler: you should autogenerate this IDs and place them in the resources/values/ids.xml. Fine. After then i can use them from code. In the code you can use them very simple(just type Resource.Id.) and you get the autogenerated IDs. But what happens when an older ID modified by the system. You need to find and replace everywhere. Or it is happens never. If you don't need the ID or the view in the layout xml it will be deleted from the ids.xml and you cannot use it in the code. And it will never happen to the system rename an older id what you use in the code, because you need to rename it everywhere where you use it. Ok i understand it. Thank you for the explaining.

  • CortezCortez USMember ✭✭✭

    Hmm... or you should updating this ids.xml every time, just there is a validating to don't set two ID with the same name?

  • FZelleFZelle DEMember ✭✭✭

    No, you are getting this wrong.

    If you use axml for the View you just put a "@+id/NameOfControl" in there and the ID will be autogenerated and you can use it in your software.

    Only if you want to generate Controls in Code by hand, you have to provide a unique ID yourself.

  • CortezCortez USMember ✭✭✭

    Hmmm FZelle!

    I don't understand. Ok i have two ways to create View; from code or in xml. In xml i can create a static layout for example. With TextViews, EditTexts and Buttons i can create an e-mail for example(subjet, message, destination e-mail address). I set an ID for every EditTexts and for the send button for example, because in the editext i want to validate the e-mail address, and moderate the subject and the message. After then i want to detect the button click event. Ok i can get this view by FindViewByID(Resource.Id.). But in this case the IDs stored in the Resource.Designer.cs i think. This file is autogenerated. But this is not a resource/values/ids.xml file. I set the ID name in the layout xml file. After that i can get this id from this Resource.Designer.cs. I can detect this IDs generated by system because if i don't save the layout xml file and/or don't clear the project, when i type the Resource.Id. i will not find the id. Another way. When i want from code creating for example 20 buttons(i don't know why it just an example) i can create 20 buttons from iteration(for cycle) and place it to not hide eachother. After then i can organize my IDs what i use from my code, but i must handling this resource file. And i can get this IDs from my resource file when i want to use it or something.

  • nodoidnodoid GBMember, Beta ✭✭✭

    It's simple enough…

    Button myButton = new Button();
    // set the bits for the button
    myButton.Tag = 5;
    myButton.Clicked += HandleMyButton;
    
    private void HandleMyButton(object sender, EventArgs e)
    {
        Button myNewButton = (Button)sender;
        int whichOne = (int)myNewButton.Tag;
        // do stuff
    }
    

    Now, the fun thing comes if you're doing lots of buttons

    for (int i = 0; i < 10; ++i)
    {
        Button btnEg = new Button();
        // do stuff for the button
        btnEg.Tag = i;
        btnEg.Clicked += HandlebtnEg;
    }
    

    if you example the Tag in HandlebtnEg, you'll find they're all 10, so you will need this

    for (int i = 0; i < 10; ++i)
    {
        Button btnEg = new Button();
        // do stuff for the button
        int m = new int();
        m = i;
        btnEg.Tag = m;
        btnEg.Clicked += HandlebtnEg;
    }
    

    then the tags work.

    No need for stuff in xml, just good ol' fashioned C# :)

  • CortezCortez USMember ✭✭✭

    Wait wait wait something is wrong. FZelle and Cheesebaron said the opponent. Cheesebaron said the only positive thing that i can organize my IDs in resource(resource/values/ids.xml) that these IDs are autogenerated and unique. But here developer.android.com/guide/topics/resources/more-resources.html by the ID section the article says i can create these IDs by myself. I declare IDs and after then i can use it in XML and in code. In XML i don't need to create it again (@+id/) just use it (@id/) because it exists in the ids.xml resource file. But when i don't use this resource file and create it from XML (autogenerated, with @+id/myButton) the result will be the Resource.Designer.cs file. This file is really autogenerated by system. After then i can use my IDs from code: Resource.Id.myButton. But this is not a resource file, we find it in the Resources folder but it looks like code not an XML. When i create my views from code i don't need to get his ID because i have the reference(Button b = new Button();). I can set it (button.Id = 10;) but i don't know where will be placed; in the Resource.designer.cs or in the resources/values/ids.xml. But it is possible that it wouldn't be unique because i set the Id.

  • FZelleFZelle DEMember ✭✭✭
    1. PLEASE USE LINEBREAKS. the way you write is to hard to read.

    2. Another please, read the thing correct.

    If you create a ids.xml file, you create the numbers, and therefore you are responsible for generating them uniquely.

    But because you do this in one file it's easier for them to be unique.
    These ID's then get automatically converted into const values in the resources.cs so you can access them.

  • CortezCortez USMember ✭✭✭

    Ok sorry. I understand the concept now, but i expected something else.

  • Shakeel.AhmadShakeel.Ahmad USMember

    hi,
    please help me in this problem !
    how can i set multiple resources visibility in my project, if number of buttons or other resources are not fixed ?

    for (int i = 1; i <= 4; i++)
    {
    FindViewById("Resource.Id.btnId"+i).Visibility = ViewStates.Visible; // for btnId1
    FindViewById("Resource.Id.imgId"+i).Visibility = ViewStates.Gone; // for imgId1
    }

    Advance thanks for you.

  • RobertBruceRobertBruce USMember ✭✭✭
    edited March 2016

    For API 17 and higher, you can use the following to generate unique IDs:

    MyCustomView.Id = View.GenerateViewId();

Sign In or Register to comment.