Binding a picker to mvvm command Xamarin forms
Asked Answered
S

5

16

I have been looking everywhere to try and solve this issue, I have not been using Xamarin forms for long but I thought it would have been easy. I am trying to bind a picker selecteditemchanged to a command in the view model, I am using FreshMVVM and Xamarin forms version 2.3.4.214-pre5, I am able to bind the data from the view model but there is no Command option in the picker.

Any help would be appreciated. Thank you

Stopoff answered 24/3, 2017 at 16:21 Comment(1)
I think there is a SelectedItem property that change when you select a value. Which command are you searching for?Degas
S
23

I have been able to get a working solution:

First off I installed Xamarin Forms version 2.3.4.214-pre5, it is working just fine. Then with the help of the Xamarin Forum, I was given a solution, which is as-follows:

1 - Install the Behaviors.Forms NuGet package by running Install-Package Behaviors.Forms in the NuGet package manager console.

2 - Then include the following namespace in the XAML page:

<ContentPage xmlns:behaviors="clr-namespace:Behaviors;assembly=Behaviors">
</ContentPage>

3 - Then add the Picker.Behaviors attribute in the Picker tag:

<Picker x:Name="MyPicker"
          ItemsSource="{Binding IdentityProviders}"
          HorizontalOptions="FillAndExpand" Title="Identity Provider"
          Margin="10"
          ItemDisplayBinding="{Binding Description}">
    <Picker.Behaviors>
          <behaviors:EventHandlerBehavior EventName="SelectedIndexChanged">
              <behaviors:InvokeCommandAction Command="{Binding SelectedProviderChanged}" />
          </behaviors:EventHandlerBehavior>
    </Picker.Behaviors>
</Picker>

If you want to pass the data back as a parameter then include the following after the command CommandParameter="{Reference MyPicker}"

That solved my problem, I hope this helps: The help I got was from this post MVVM Light - How to use the selectedIndexChanged event in viewModel

Stopoff answered 24/3, 2017 at 18:7 Comment(3)
That's a nice trick. I believe it should be easily portable to any kind of control. Thanks for sharing!Misfeasance
The Picker is then bound to the ViewModel which is wrong. Just monitor the property in the view modelSteepen
Thank you for a very thorough an answerRationalism
S
9

All you need to do is monitor the SelectedItem property in your view model.

        private ObservableRangeCollection<UserViewModel> _users = new ObservableRangeCollection<UserViewModel>();
        public ObservableRangeCollection<UserViewModel> Users
        {
            get => _users;
            set { _users = value; OnPropertyChanged(); }
        }

    private User _selectedUser;
        public UserModelView CurrentUser
        {
            get => _selectedUser;
            set { _selectedUser = value; 
                  //Do Some stuff with your new user(); 
                  OnPropertyChanged(); 
}
        }



<Picker WidthRequest="100" 
                ItemsSource="{Binding Users}"
                ItemDisplayBinding="{Binding Name}"
                SelectedItem="{Binding CurrentUser, Mode=TwoWay}" />
Steepen answered 22/4, 2019 at 16:46 Comment(2)
This seems to me as the cleaner and more pure MVVM alternative.Edgar
this only works if you aren't dealing with data sources that require async operations I think?Leija
I
3

I found the solution here: https://forums.xamarin.com/discussion/71084/call-command-programmatically-without-binding-to-button

In file.xaml:

<Picker
       SelectedIndexChanged="Handle_SelectedIndexChanged"
       ItemsSource="{Binding FilterOptions}"
       ItemDisplayBinding="{Binding Value}" />

In file.xaml.cs:

TransactionViewModel ViewModel { get => BindingContext as TransactionViewModel; set => BindingContext = value; }

void Handle_SelectedIndexChanged(object sender, System.EventArgs e)
{
    var selectedOption = (sender as Picker).SelectedItem;
    ViewModel.ChangeOptionCommand.Execute(selectedOption);
}

In view-model:

public ICommand ChangeOptionCommand { get; private set; }

public TransactionViewModel()
{
    ChangeOptionCommand = new Command<KeyValuePair<string, string>>(ChangeOption);
}

void ChangeOption(KeyValuePair<string, string> selectedOption)
{
    Debug.WriteLine(selectedOption);
}
Idealize answered 11/9, 2018 at 22:56 Comment(2)
This option looks good but, IMO, the answer proposed by @NickTurner seems to be a better choice.Edgar
I actually think this is the best solution. The official docs do this a lot where they propigate something from the xaml.cs to the view model where commands aren't available. But in the constructor set it as BindingContext = _viewmodel =new NewViewModel(); then you have access to _viewmodelLeija
N
0

Not sure of command , but whenever there is change in picker value, "SelectedItem" value is also being changed. We can bind object from viewmodel to "SelectedItem". On setting value for this object, we can perform out required things at property set.In this way no need to write "SelectedIndexChanged" function.

Newborn answered 23/7, 2021 at 11:17 Comment(0)
S
-4

To run code when a picker item is selected, specify the SelectedIndexChanged property of your picker:

<Picker x:Name="myPicker" SelectedIndexChanged="indexChanged"/>

Then in your code behind add your indexChanged method:

void indexChanged(object sender, EventArgs e) 
{
    //Your code here
}

Then, when a user selects a different item from your picker, it will run the indexChanged method.

Stinko answered 24/3, 2017 at 16:35 Comment(2)
That would work but I am trying to bind it to mvvm command where I update the model as selections are made. I need to bind it to command.Stopoff
Check out this website and under the Commanding with ViewModels section it shows the Views which support the Command Interface. Picker isn't one of them, so if you have to use a Command, a Picker won't work for you.Stinko

© 2022 - 2024 — McMap. All rights reserved.