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******
@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
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?
@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:
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}"
Yes the Model i load NameAndValue from looks like this:
I just tried both Name and NameAndValue, and neither will work when I use the SelectedItem property.
Do you implement INotifyPropertyChanged?
Yes I do in the BaseViewModel which UValueViewModel is based of.
@AlessandroCaliaro
I ended up solving it without MVVM.
I used this for the XAML:
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:
Not the optimal solution, but it works for know.