GuyWithGlasses
GuyWithGlasses

Reputation: 51

Can not pass binding context through Navigation.pushasync with collectionview in xamarin

I am new to Xamarin and am making a small prototype application. Since this is a pilot project, I am keeping it simple and not using MVVM.

Expected output: I have a collection view and when I select an item from that view, I would like to bind the data from that Item, and navigate to a new page. I want the new page to be binded with the data I selected from the collection view as there will be a couple buttons on that page with different options.

Problem: When the item is selected from the collection view, I use Navigation.pushasync to open a new page. Inside of that routing action, I set the binding context to the data from the selected item. When I navigate to the page, none of the page is populated with data from the binding context I set in the previous page.

Comment: I had this working with a list view. But I wanted more flexibility in my styles for my list, so I am trying a collection view. I am having trouble trying to understand the way to bind data with a collection list vs a listview.

Main Page View:

MainPageView

MainPage.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" 
             x:Class="Notes.MainPage"
             Title="My Numbers">
    <ContentPage.ToolbarItems>
        <ToolbarItem Text="+"
                     Clicked="OnNumberAddedClicked" />
        <ToolbarItem Text="Q"
                     Clicked="GetCount"/>
        <ToolbarItem Text="L"
                     Clicked="GetLast"/>
    </ContentPage.ToolbarItems>
    <ContentPage.Content>
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>

            <CollectionView x:Name="listView"
                            SelectionMode="Single"
                            ItemsSource="{Binding listView}">

                <CollectionView.ItemTemplate>
                    <DataTemplate>
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="100"/>
                                <ColumnDefinition Width="*"/>
                            </Grid.ColumnDefinitions>

                            <StackLayout Orientation="Vertical"
                                         Grid.Column="1">
                                <Label Text="{Binding MyNumber}" FontSize="Title"/>
                                <Label Text="{Binding DateAdded}" FontSize="Subtitle"/>
                            </StackLayout>
                        </Grid>
                    </DataTemplate>
                </CollectionView.ItemTemplate>
            </CollectionView>
        </Grid>
    </ContentPage.Content>
</ContentPage>

MainPage.xaml.cs:

using System;
using Xamarin.Forms;
using Notes.Models;

namespace Notes
{
    public partial class MainPage : ContentPage
    {
        public MainPage()
        {
            InitializeComponent();

            listView.SelectionChanged += ListView_SelectionChanged;
        }

        async void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            var num = e.CurrentSelection;
            if (num != null)
            {
                await Navigation.PushAsync(new ActionsPage
                {
                    BindingContext = num as NUM
                });
            }
        }

        protected override async void OnAppearing()
        {
            base.OnAppearing();

            listView.ItemsSource = await App.Database.GetNumbersAsync();
        }
    }
}

Action Page View: The circle is where the label is supposed to be, but the data won't bind.

ActionsPage

ActionsPage.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" 
             x:Class="Notes.ActionsPage"
             Title="NUM Actions">
    <StackLayout>
        <Label Text="{Binding myNumber}"
               FontSize="Large"
               VerticalOptions="CenterAndExpand"
               HorizontalOptions="Center" />

        <Button Text="Delete NUM"
                VerticalOptions="CenterAndExpand"
                HorizontalOptions="Center"
                Clicked="OnDeleteButtonClicked" />
    </StackLayout>
</ContentPage>

ActionsPage.xaml.cs:

using Notes.Models;
using System;
using Xamarin.Forms;

namespace Notes
{
    public partial class ActionsPage : ContentPage
    {
        public ActionsPage()
        {
            InitializeComponent();
        }

        async void OnDeleteButtonClicked(object sender, EventArgs e)
        {
            var num = (NUM)BindingContext;
            await App.Database.DeleteNumAsync(num);
            await Navigation.PopAsync();
        }
    }
}

Any help is appreciated

Upvotes: 0

Views: 1170

Answers (1)

Wendy Zang - MSFT
Wendy Zang - MSFT

Reputation: 10978

The simple way to pass value on navigation is just to pass an argument in the constructor.

MainPage SelectionChanged event:

private async  void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        var num = e.CurrentSelection[0] as NUM;

        if (num != null)
        {
          await Navigation.PushAsync(new ActionsPage(num));

        }
    }

ActionPage:

public partial class ActionsPage : ContentPage
 {
    public int myNumber { get; set; }
    public ActionsPage(NUM num)
    {
        InitializeComponent();
        myNumber = num.MyNumber;

        this.BindingContext = this;
    }

    async void  OnDeleteButtonClicked(System.Object sender, System.EventArgs e)
    {
        //var num = (NUM)BindingContext;
        //await App.Database.DeleteNumAsync(num);
        //await Navigation.PopAsync();
    }
}

enter image description here

Upvotes: 1

Related Questions