I'm not seeing the button I added.

AhmedovAhmedovAhmedovAhmedov USMember ✭✭
edited September 14 in Xamarin.Forms

I'm trying to add programmatically a visual element as a child of another one and its working fine until the parent is a ViewCell.

<ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <StackLayout Padding="25">
                        </StackLayout>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
private void AddButtons()
        {
            IEnumerable<PropertyInfo> pInfos = (ItemsListView as ItemsView<Cell>).GetType().GetRuntimeProperties();
            var templatedItems = pInfos.FirstOrDefault(info => info.Name == "TemplatedItems");
            if (templatedItems != null)
            {
                var cells = templatedItems.GetValue(ItemsListView);
                foreach (ViewCell cell in cells as ITemplatedItemsList<Cell>)
                {
                    if (cell.BindingContext != null && cell.BindingContext is AnswerItem)
                    {
                        var stackLayout = cell.View as StackLayout;
                        stackLayout.BackgroundColor = Color.Blue;
                        Button myButton = new Button { Text = "My Button" };
                        myButton.BackgroundColor = Color.Red;
                        stackLayout.Children.Add(myButton);
                    }
                }
            }
        }

The code is copied from stackoverflow. I'm seeing that the button exists in stackLayout children, but not on my screen. The background of the stackLayout is not Blue as well.

My question is: Why I don't see myButton?

Best Answer

  • AshokAshAshokAsh US ✭✭
    edited September 25 Accepted Answer

    @AhmedovAhmedov you can add visual element in view cell at run time. you have to create custom stack layout that accepts Item source ,then run time you can assign value to Item source .

    create List mybottons=new list.....

    <ViewCell>
    <CustomStack  itemSource={Binding mybuttons}></CustomStack>
    </ViewCell>
    

Answers

  • LuisDavidDelaCruzLuisDavidDelaCruz Member ✭✭✭
    edited September 15

    it's because in your XAML code you don't have the Stacklayout that you created in code-behind
    var stackLayout = cell.View as StackLayout;

    try adding the x:name property in your StackLayout in example

    <ViewCell>
    <StackLayout Padding="25" x:Name="myLayout">
    </StackLayout>
    </ViewCell>
    

    and use myLayout instead the stackLayout instance

    myLayout.Children.Add(myButton);
    

    another question... when do you execute the method AddButtons(); ?

  • AhmedovAhmedovAhmedovAhmedov USMember ✭✭

    @LuisDavidDelaCruz said:
    it's because in your XAML code you don't have the Stacklayout that you created in code-behind
    var stackLayout = cell.View as StackLayout;

    try adding the x:name property in your StackLayout in example

    <ViewCell>
    <StackLayout Padding="25" x:Name="myLayout">
    </StackLayout>
    </ViewCell>
    

    and use myLayout instead the stackLayout instance

    myLayout.Children.Add(myButton);

    Thanks for you response. Did you succeed in adding a child or better changing the background color?
    What I tried, without an effect is:

    <ViewCell x:Name="TheCell">
             <StackLayout Padding="25" x:Name="myLayout" BackgroundColor="Red">
    
    var myLayout = cell.View.FindByName<StackLayout>("myLayout");
    myLayout.BackgroundColor = Color.Blue;
    

    and also

    var myLayout = cell.FindByName<StackLayout>("myLayout");
    myLayout.BackgroundColor = Color.Blue;
    

    There is no change. In both cases with and without setting the Name, I'm seeing in debug that the stackLayout background is red before the change and blue after, so its the correct layout. However on my screen all cells are still red. What I'm missing?

    when do you execute the method AddButtons(); ?

    On a cell tap, like this:

    async void OnItemTapped(object sender, ItemTappedEventArgs args)
    
  • AshokAshAshokAsh USMember ✭✭
    edited September 24

    Hi,
    Accessing views with in a viewcell in code behind is not a good practice.
    You have create color property in model and have to assign value when some action occurs.

    Ex:

    Public class mymodel
    {
    public color bgcolor{get;set;} =color.Red;
    }

    ` In View Model:`
    
    `List<mymodel> newlst=new List<mymodel>();`
    

    public ICommand TappedCommand= new Command<mymodel> (onstacktapped);

    void onstacktapped(mymodel obj)
    {
    obj.bgcolor=color.Blue; //This will change the color of stack in particular cell.
    }

    In xaml:

           `<ContentPage X:Name="myPage"  >` // you have to add name to contentpage 
    

    <Listview ItemSource=" {Binding newlst}">
    <ListView.ItemTemplate>
    <DataTemplate>
    <ViewCell>
    <StackLayout BackgroundColor={Binding bgcolor}>
    <StackLayout.GestureRecognizers>
    <TapGestureRecognizer
    Command="{Binding Path=BindingContext.TappedCommand, Source={x:Reference myPage}}" CommandParameter="{Binding .}" >

    /// Here we referencing current page's bindingcontext to assign command to the tap event. View Cell only refer the List View's ItemSource as Binding context.

       ` </StackLayout.GestureRecognizers>`
    

    </StackLayout>
    </ViewCell>
    </DataTemplate>
    </ListView.ItemTemplate>
    ```

  • AhmedovAhmedovAhmedovAhmedov USMember ✭✭

    @Ashokkumaar Thanks for the effort put in your answer. I do already using code similar to it:

    <ListView  ItemTapped ="OnItemTapped">
    
    async void OnItemTapped(object sender, ItemTappedEventArgs args)
            {
                var item = args.Item as AnswerItem;
    

    What I'm trying to achieve as the title says, is not chaging the color of a specific cell, but adding visual elements to a ViewCell on the fly.

  • AshokAshAshokAsh USMember ✭✭
    edited September 25
    Fine @AhmedovAhmedov . You got solution for that?
  • AhmedovAhmedovAhmedovAhmedov USMember ✭✭
    edited September 25

    @Ashokkumaar No, I was never able to add a child to a viewCell outside the xaml. I'm starting to suspect that there is something wrong in the way I'm initializing the viewmodel, because image animations are not working as well. I'm going to open a new thread for that.

  • AshokAshAshokAsh USMember ✭✭
    edited September 25 Accepted Answer

    @AhmedovAhmedov you can add visual element in view cell at run time. you have to create custom stack layout that accepts Item source ,then run time you can assign value to Item source .

    create List mybottons=new list.....

    <ViewCell>
    <CustomStack  itemSource={Binding mybuttons}></CustomStack>
    </ViewCell>
    
  • AhmedovAhmedovAhmedovAhmedov USMember ✭✭

    @Ashokkumaar Oh, I see. Thats a bit complicated. I find many things to be more complicated than expected with Xamarin forms. Thank you for your patience!

Sign In or Register to comment.