Forum Xamarin.Forms
We are excited to announce that the Xamarin Forums are moving to the new Microsoft Q&A experience. Q&A is the home for technical questions and answers at across all products at Microsoft now including Xamarin!

We encourage you to head over to Microsoft Q&A for .NET for posting new questions and get involved today.

Picker SelectedItemChanged with MVVM

Hello Xamarin Profs

I'm new to MVVM and I'm trying to bind a label together with my picker, but I want another value from the selected picker items.

I'm calling a list/Observable Collection from another page as my pickers items source, and then use ItemDisplayBinding to choose the value of the items I want to display like below XAML:

        <Picker x:Name="picker1"
                        Title="Vælg bygningsdel"
                        HorizontalOptions="FillAndExpand"
                        ItemsSource="{Binding Items}"
                        ItemDisplayBinding="{Binding NameAndValue}"
                        IsVisible="true"/>

                    <!--//BINDING//    StringFormat='λ = {0}'}-->
                    <Label Text="This is a value" VerticalOptions="CenterAndExpand" HorizontalOptions="End" />

I then want the selected items "UValue" property to be displayed in the label at the bottom of the XAML - using MVVM and bindings.

My ViewModel for the view looks like:

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using LommeKonstruktoren.Models;
using Xamarin.Forms;
using LommeKonstruktoren.Services;
using System.Diagnostics;
using System.Threading.Tasks;
using System.ComponentModel;
using LommeKonstruktoren.Views;

namespace LommeKonstruktoren.ViewModels
{

    public class UValueViewModel : BaseViewModel
    {
        private Item _selectedItem;

        public double KorrektionForSpalterValue { get; }
        public ObservableCollection<Item> Items { get; }
        public Command LoadItemsCommand { get; }
        public Command AddItemCommand { get; }
        public Command SelectCorrection { get; }
        public Command<Item> ItemTapped { get; }
        public double Picker1Value { get; }

        public UValueViewModel()
        {
            Title = "U-værdiberegning";
            Items = new ObservableCollection<Item>();
            LoadItemsCommand = new Command(async () => await ExecuteLoadItemsCommand());
            SelectCorrection = new Command(SelectCorrectionButton);
        }


        private async void SelectCorrectionButton(object obj)
        {
            await Shell.Current.GoToAsync(nameof(BindersCorrectionPage));
        }

        // code for loading the items from materials list to the view // used for pickers

        async Task ExecuteLoadItemsCommand()
        {
            try
            {
                Items.Clear();
                var items = await DataStore.GetItemsAsync(true);

                foreach (var item in items)
                {
                    Items.Add(item);
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex);
            }
            finally
            {
                IsBusy = false;
            }
        }

        // Code for when view appears
        public void OnAppearing()
        {
            IsBusy = true;
        }
    }
    }

And the view it self looks like this:

How would I approach this? I need to use the values coming from the list, as the list is changed by the user (including the values).

Without MVVM and the list I would be able to solve this with the SelectedIndexChange event, but I'm not sure how it should be done in MVVM.

Hope someone can help.

****The app is in Danish, so ask if anything needs to be translated for the sake of helping and I'd gladly do it******

Best Answer

  • mndevelopmentsmndevelopments Member ✭✭
    edited October 19 Accepted Answer

    @AlessandroCaliaro
    I ended up solving it without MVVM.

    I used this for the XAML:

                        <Picker x:Name="picker1"
                            Title="Vælg bygningsdel"
                            HorizontalOptions="FillAndExpand"
                            ItemsSource="{Binding Items}"
                            ItemDisplayBinding="{Binding NameAndValue}"
                            IsVisible="true"
                            Unfocused="picker1_Unfocused"
                            />
    
                        <Label x:Name="picker1LAbel" Text="This is value" VerticalOptions="CenterAndExpand" HorizontalOptions="End" />
    

    And the in the code behind for the page I called the list from the database, assigned it to items - then in the Unfocused event handler I did:

            void picker1_Unfocused(System.Object sender, System.EventArgs e)
            {
                var selectedItem = picker1.SelectedIndex;
    
                var selectedUValue = Items[selectedItem].UValue;
    
                 picker1LAbel.Text = "Lampda" + selectedUValue;
    
            }
    

    Not the optimal solution, but it works for know.

Answers

  • AlessandroCaliaroAlessandroCaliaro ITMember ✭✭✭✭✭

    I think Picker has a "SelectedItem" property. Bind it to a Property in your Model then bind the Property "Text" of Label to the same property. Is it clear?

  • mndevelopmentsmndevelopments Member ✭✭

    @AlessandroCaliaro - Thank you for the suggestion.

    When I try to do that I get the following error:

    Error XFC0045: Binding: Property "UValue" not found on "LommeKonstruktoren.ViewModels.UValueViewModel". (XFC0045) (LommeKonstruktoren) XamlC

    I'm confused to why it targets UValueViewModel and not the Models.Item which the ItemsSource and ItemDisplayBinding is.

    The XAML looks like this:

                        <Picker x:Name="picker1"
                            Title="Vælg bygningsdel"
                            HorizontalOptions="FillAndExpand"
                            ItemsSource="{Binding Items}"
                            ItemDisplayBinding="{Binding NameAndValue}"
                            IsVisible="true"
                            SelectedItem="{Binding UValue}"/>
    
                        <!--{Binding SelectedItems.UValue, StringFormat='λ = {0}'}-->
                        <Label Text="{Binding UValue}" VerticalOptions="CenterAndExpand" HorizontalOptions="End" />
    
  • AlessandroCaliaroAlessandroCaliaro ITMember ✭✭✭✭✭

    I don't understand...

    Your picker has a ITemSource that is "Items".

    Items is of type "Item".

    UValue must be of tipe "Item" and you should visualize something like Text="{Binding UValue.NameAndValue}"

  • mndevelopmentsmndevelopments Member ✭✭

    Yes the Model i load NameAndValue from looks like this:

    using System;
    
    namespace LommeKonstruktoren.Models
    {
        public class Item
        {
            public string Id { get; set; }
            public string Name { get; set; }
            public string UValue { get; set; }
            public string Description { get; set; }
    
            public string NameAndValue
            {
                get { return Name + " λ = " + UValue; }
            }
        }
    }
    

    I just tried both Name and NameAndValue, and neither will work when I use the SelectedItem property.

  • AlessandroCaliaroAlessandroCaliaro ITMember ✭✭✭✭✭

    Do you implement INotifyPropertyChanged?

  • mndevelopmentsmndevelopments Member ✭✭

    Yes I do in the BaseViewModel which UValueViewModel is based of.

  • mndevelopmentsmndevelopments Member ✭✭
    edited October 19 Accepted Answer

    @AlessandroCaliaro
    I ended up solving it without MVVM.

    I used this for the XAML:

                        <Picker x:Name="picker1"
                            Title="Vælg bygningsdel"
                            HorizontalOptions="FillAndExpand"
                            ItemsSource="{Binding Items}"
                            ItemDisplayBinding="{Binding NameAndValue}"
                            IsVisible="true"
                            Unfocused="picker1_Unfocused"
                            />
    
                        <Label x:Name="picker1LAbel" Text="This is value" VerticalOptions="CenterAndExpand" HorizontalOptions="End" />
    

    And the in the code behind for the page I called the list from the database, assigned it to items - then in the Unfocused event handler I did:

            void picker1_Unfocused(System.Object sender, System.EventArgs e)
            {
                var selectedItem = picker1.SelectedIndex;
    
                var selectedUValue = Items[selectedItem].UValue;
    
                 picker1LAbel.Text = "Lampda" + selectedUValue;
    
            }
    

    Not the optimal solution, but it works for know.

Sign In or Register to comment.