简体   繁体   中英

List of Buttons with Binding and Command in Xamarin

I'm working on a Xamarin App where I want to dynamically display a list of Registry Numbers from a Class Registry.
After the list of numbers is displayed, the user should choose one of them to login in the App.

I have decided that this list will be displayed as a list of Buttons, because once the user clicks it, nothing else needs to be done. However, most of documentation regarding Binding and ListView does not use Buttons as displaying element.

I have decided to follow the steps on this excellent video but I keep receiving the following error:

Binding: 'LocalCommand' property not found on '31348', target property: 'Xamarin.Forms.Button.Command'
Binding: 'LocalCommand' property not found on '10227', target property: 'Xamarin.Forms.Button.Command'

Actually, 31348 and 10227 are the numbers that I want to display. And indeed I indicated them as the Binding context at some point. But I would like to "change" that Binding so I can invoke the LocalCommand method. Probably implementing the LocalCommand in the object would solve the issue, but I definitely don't want to do that!

Questions:

  1. Is there a better and simpler way to do this?
  2. How can I do to "bring back" the Binding to the LocalCommand?

I'm still learning about Binding, so any tips would be really useful!
Thanks!

RegistryPage.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:behavior1="clr-namespace:SPConsigMobile.Utils"
             x:Class="App.Views.RegistryPage"
             BackgroundColor="{StaticResource AppBackgroundColor}"
             Title="App"
             NavigationPage.HasNavigationBar="false">
    <ContentPage.Content>
        <ListView x:Name="RegistryView"
                    ItemsSource="{Binding User.Registry}"
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <Button Text="{Binding Number}"
                                Command="{Binding LocalCommand}"/>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </ContentPage.Content>
</ContentPage>

RegistryPage.xaml.cs

namespace App.Views
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class RegistryPage : ContentPage
    {
        public RegistryPage()
        {
            InitializeComponent();
            RegistryView.ItemsSource = User.Registries;
        }
        public ICommand LocalCommand => new Command(CommandClicked);

        private void CommandClicked()
        {
            Console.WriteLine("Command Button Clicked!");
        }
    }
}

In general when you set the ItemSource property of a control (in this case of your ListView), you have also to set the DataTemplate.

Now, the BindingContext of view inside the DataTemplate is an item of the collection you have binded to. In your case, because you have set the ItemSource to be a Collection of PhoneNumber, the bindingContext of each view is a PhoneNumber.

So when you are trying to acess your command with 'Command="{Binding LocalCommand}"', what you are doing is to search a LocalCommand Property inside a PhoneNumber class. What you need instead is to search it inside your Page class. So, give a name to your ContentPage with x:Name, then reference the source to your command binding to be the Root Page, and the Path to be the path to the command, starting from the Source (so NumberSelectedCommand in my example). the command parameter should be instead exactly the number, so it's an empty path Binding.

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="App1.RegistryPage"
             x:Name="Root"
             >

    <StackLayout>
        <ListView x:Name="RegistryView"
                    ItemsSource="{Binding User.Registry}"
            <ListView.ItemTemplate>
            <DataTemplate>
                <ViewCell>
                    <Button Text="{Binding Number}"
                            Command="{Binding Source={x:Reference Root}, Path=NumberSelectedCommand}"
                            CommandParameter="{Binding}"
                            />
                </ViewCell>
            </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </StackLayout>

</ContentPage>

RegistryPage.xaml.cs

    [XamlCompilation(XamlCompilationOptions.Compile)]  
    public partial class RegistryPage : ContentPage
    {
        public RegistryPage()
        {
            InitializeComponent();
            RegistryView.ItemsSource = User.Registries;
            NumberSelectedCommand = new Command<PhoneNumber>(OnNumberSelected);
        }


        // Commands
        public ICommand NumberSelectedCommand { get; }


        // Commands Handlers
        private void OnNumberSelected(PhoneNumber selectedNumber)
        {
            // Do what you need with selected number.
        }
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM