dcpartners
dcpartners

Reputation: 5456

Selected item not working in Picker

In our edit page, we have an issue to populate the value into Selected Item in picker and it won't select for some reason from the LoadCourses() or LoadRoundCategories() either.

Any ideas?

Here's the code:

ViewModel

public class EditGolfRoundViewModel : INotifyPropertyChanged
{
    ApiServices _apiServices = new ApiServices();

    private string _message;
    private ObservableCollection<GolfCourse> _courses;
    private ObservableCollection<GolfRoundCategory> _roundCategories;
    private object_selectedGolfCourse;
    private GolfRoundCategory _selectedGolfRoundCategory;
    private GolfRound _golfRound;

    public EditGolfRoundViewModel()
    {
        _selectedGolfCourse = new GolfCourse();
        _selectedGolfRoundCategory = new GolfRoundCategory();
        LoadCourses();
        LoadRoundCategories();
    }

    public GolfRound GolfRound
    {
        get { return _golfRound; }
        set
        {
            _golfRound = value;
            OnPropertyChanged();
        }
    }


    public string Message
    {
        get { return _message; }

        set
        {
            _message = value;
            OnPropertyChanged();
        }
    }

    public ObservableCollection<GolfCourse> GolfCourses
    {
        get { return _courses; }
        set
        {
            if (_courses != value)
            {
                _courses = value;
                OnPropertyChanged();
            }

        }
    }

    public ObservableCollection<GolfRoundCategory> GolfRoundCategories
    {
        get { return _roundCategories; }
        set
        {
            _roundCategories = value;
            OnPropertyChanged();
        }
    }

    public object SelectedGolfCourse
    {
        get { return _selectedGolfCourse; }
        set
        {
            _selectedGolfCourse = value;
            var golfCourse = _selectedGolfCourse as GolfCourse;
            Guid tempGolfCourseID = golfCourse.GolfCourseID;
            OnPropertyChanged("SelectedGolfCourse");
        }
    }


    public GolfRoundCategory SelectedGolfRoundCategory
    {
        get { return _selectedGolfRoundCategory; }
        set
        {
            _selectedGolfRoundCategory = value;
            OnPropertyChanged();
        }
    }



    public ICommand EditCommand 
    { 
        get
        {
            return new Command(async() =>
            {
                GolfRound.GolfCourseID = SelectedGolfCourse.GolfCourseID;
                GolfRound.GolfCourse = SelectedGolfCourse;
                GolfRound.GolfRoundCategoryID = SelectedGolfRoundCategory.GolfRoundCategoryID;
                GolfRound.GolfRoundCategory = SelectedGolfRoundCategory;
                GolfRound.LastModifiedUTC = System.DateTime.Now;

                await _apiServices.PutGolfRoundAsync(GolfRound, Settings.AccessToken);
            });
        }

    }

    public ICommand DeleteCommand
    {
        get
        {
            return new Command(async () =>
            {
                await _apiServices.DeleteGolfRoundAsync(GolfRound.GolfRoundID, Settings.AccessToken);
            });
        }

    }

    public event PropertyChangedEventHandler PropertyChanged;

    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    private async void LoadCourses()
    {
        GolfCourses = new ObservableCollection<GolfCourse>(await _apiServices.GetGolfCoursesAsync(Settings.AccessToken));
    }

    private async void LoadRoundCategories()
    {
        GolfRoundCategories = new ObservableCollection<GolfRoundCategory>(await _apiServices.GetGolfRoundCategoriesAsync(Settings.AccessToken));
    }

}

View - XAML

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
         xmlns:viewModels="clr-namespace:AthlosifyMobile.ViewModels.Golf"
         x:Class="AthlosifyMobile.Views.EditGolfRoundPage">

<StackLayout Orientation="Vertical" VerticalOptions="Center" Spacing="30" Padding="30">
    <Entry Text="{Binding GolfRound.Name}" Placeholder="name" FontSize="Default" />
    <Entry Text="{Binding GolfRound.Notes}" Placeholder="notes" FontSize="Default" />
    <Entry Text="{Binding GolfRound.DailyHandicap}" Placeholder="daily handicap" FontSize="Default" />
    <Label Text="Date" />
    <DatePicker Date="{Binding GolfRound.TeeOffUTC}" 
                Format="D"
                Margin="30, 0, 0, 30"  />
    <Picker x:Name="pCourse" Title="Course" ItemsSource="{Binding GolfCourses}" 
            SelectedItem="{Binding SelectedGolfCourse, Mode=TwoWay}" 
            ItemDisplayBinding="{Binding Name}"></Picker>
    <Entry Text="{Binding GolfRound.GolfCourse.Name}" Placeholder="selected golf course" FontSize="Default" />
    <Picker x:Name="pCategory" Title="Category" ItemsSource="{Binding GolfRoundCategories}" 
            SelectedItem="{Binding SelectedGolfRoundCategory, Mode=TwoWay}"
            ItemDisplayBinding="{Binding Name}"></Picker>
    <Entry Text="{Binding SelectedGolfRoundCategory.Name}" Placeholder="selected round category" FontSize="Default" />
    <Button Command="{Binding EditCommand}" Text="Edit Round" />
    <Button Command="{Binding DeleteCommand}" Text="Delete Round" />

    <Label Text="{Binding Message}" ></Label>
</StackLayout>

View - code behind

public partial class EditGolfRoundPage : ContentPage
{
    public EditGolfRoundPage (GolfRound round)
    {
        var editGolfRoundViewModel = new EditGolfRoundViewModel();
        editGolfRoundViewModel.GolfRound = round;

        BindingContext = editGolfRoundViewModel;

        InitializeComponent ();

        //var editGolfRoundViewModel = new EditGolfRoundViewModel();
        //editGolfRoundViewModel.GolfRound = round;
        //editGolfRoundViewModel.SelectedGolfCourse = round.GolfCourse;

        //BindingContext = editGolfRoundViewModel;

    }
}

Upvotes: 11

Views: 9746

Answers (6)

Rajitha Wijayaratne
Rajitha Wijayaratne

Reputation: 726

The following is true as of Xamarin Forms v4.7.

See if you are doing this:

<Picker x:Name="DefaultEntitlement" Title="Entitlement"
    SelectedItem="{Binding SelectedOwnerEntitlement, Mode=TwoWay}"
    ItemsSource="{Binding OwnerEntitlements, Mode=TwoWay}">
</Picker>

Instead of this:

<Picker x:Name="DefaultEntitlement" Title="Entitlement"
    ItemsSource="{Binding OwnerEntitlements, Mode=TwoWay}"
    SelectedItem="{Binding SelectedOwnerEntitlement, Mode=TwoWay}">
</Picker>

Upvotes: 9

hendrathings
hendrathings

Reputation: 3775

You can try:

  • make sure your prop support INotifyPropertyChanged
  • make sure Selected Item variable has initial value
  • try debug your selected item variable, make sure has value

1. Initials

Take a look your code:

public EditGolfRoundViewModel()
{
    _selectedGolfCourse = new GolfCourse();
    _selectedGolfRoundCategory = new GolfRoundCategory();
    LoadCourses();
    LoadRoundCategories();
}

If you try to initial value Selected Item, don't do this:

_selectedGolfCourse = new GolfCourse();
_selectedGolfRoundCategory = new GolfRoundCategory();

let it null, is fine. You can do like this:

SelectedGolfRoundCategory = new GolfRoundCategory();
//or
SelectedGolfRoundCategory = dataFromAPI;

2. Assign

Take a look your code:

public ICommand EditCommand 
{ 
    get
    {
        return new Command(async() =>
        {
            GolfRound.GolfCourseID = SelectedGolfCourse.GolfCourseID;
            GolfRound.GolfCourse = SelectedGolfCourse;
            GolfRound.GolfRoundCategoryID = SelectedGolfRoundCategory.GolfRoundCategoryID;
            GolfRound.GolfRoundCategory = SelectedGolfRoundCategory;
            GolfRound.LastModifiedUTC = System.DateTime.Now;

            await _apiServices.PutGolfRoundAsync(GolfRound, Settings.AccessToken);
        });
    }
 }

You trying selected item variable insert into to object GolfRound, like this part:

  GolfRound.GolfRoundCategoryID = SelectedGolfRoundCategory.GolfRoundCategoryID;
  GolfRound.GolfRoundCategory = SelectedGolfRoundCategory;

Make sure you have INotifyPropertyChanged implement this model GolfRound for prop GolfRoundCategoryID and GolfRoundCategory. If not, it would not work. I have experience for this.

Hope this helpful.

Upvotes: 0

NKR
NKR

Reputation: 2943

Can you try once replacing your Viewmodel. I have changed the type from Object to actual type. Set the Default item while loading the items from endpoint.

public class EditGolfRoundViewModel : INotifyPropertyChanged
{
ApiServices _apiServices = new ApiServices();

private string _message;
private ObservableCollection<GolfCourse> _courses;
private ObservableCollection<GolfRoundCategory> _roundCategories;
private GolfCourse _selectedGolfCourse;
private GolfRoundCategory _selectedGolfRoundCategory;
private GolfRound _golfRound;

public EditGolfRoundViewModel()
{
    LoadCourses();
    LoadRoundCategories();
}

public GolfRound GolfRound
{
    get { return _golfRound; }
    set
    {
        _golfRound = value;
        OnPropertyChanged();
    }
}


public string Message
{
    get { return _message; }

    set
    {
        _message = value;
        OnPropertyChanged();
    }
}

public ObservableCollection<GolfCourse> GolfCourses
{
    get { return _courses; }
    set
    {
        if (_courses != value)
        {
            _courses = value;
            OnPropertyChanged();
        }

    }
}

public ObservableCollection<GolfRoundCategory> GolfRoundCategories
{
    get { return _roundCategories; }
    set
    {
        _roundCategories = value;
        OnPropertyChanged();
    }
}

public GolfCourse SelectedGolfCourse
{
    get { return _selectedGolfCourse; }
    set
    {
        _selectedGolfCourse = value;
        OnPropertyChanged("SelectedGolfCourse");
    }
}


public GolfRoundCategory SelectedGolfRoundCategory
{
    get { return _selectedGolfRoundCategory; }
    set
    {
        _selectedGolfRoundCategory = value;
        OnPropertyChanged();
    }
}



public ICommand EditCommand
{
    get
    {
        return new Command(async () =>
        {
            GolfRound.GolfCourseID = SelectedGolfCourse.GolfCourseID;
            GolfRound.GolfCourse = SelectedGolfCourse;
            GolfRound.GolfRoundCategoryID = SelectedGolfRoundCategory.GolfRoundCategoryID;
            GolfRound.GolfRoundCategory = SelectedGolfRoundCategory;
            GolfRound.LastModifiedUTC = System.DateTime.Now;

            await _apiServices.PutGolfRoundAsync(GolfRound, Settings.AccessToken);
        });
    }

}

public ICommand DeleteCommand
{
    get
    {
        return new Command(async () =>
        {
            await _apiServices.DeleteGolfRoundAsync(GolfRound.GolfRoundID, Settings.AccessToken);
        });
    }

}

public event PropertyChangedEventHandler PropertyChanged;

[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

private async void LoadCourses()
{
    GolfCourses = new ObservableCollection<GolfCourse>(await _apiServices.GetGolfCoursesAsync(Settings.AccessToken));
    if (GolfCourses != null && GolfCourses.Count() > 0)
        SelectedGolfCourse = GolfCourses[0];
}

private async void LoadRoundCategories()
{
    GolfRoundCategories = new ObservableCollection<GolfRoundCategory>(await _apiServices.GetGolfRoundCategoriesAsync(Settings.AccessToken));
    if (GolfRoundCategories != null && GolfRoundCategories.Count() > 0)
        SelectedGolfRoundCategory = GolfRoundCategories[0];

}

}

Upvotes: 0

Ben
Ben

Reputation: 2995

Implement IEquatable for class of property used in SelectedItem:

public class GolfCourse : IEquatable<GolfCourse>
{
    ...
    public bool Equals(GolfCourse other)
    {
        if (other == null) return false;
        return (this.Name.Equals(other.Name));
    }
}

Usage, assuming ItemsSource contains an object with value of Name as shown below:

SelectedGolfCourse = new GolfCourse { Name = "Course 2" };

Upvotes: 21

Ronak Shetiya
Ronak Shetiya

Reputation: 980

Xaml

    <Picker x:Name="ProductPicker" WidthRequest="220"    HeightRequest="35" Title="Select" ItemsSource="{Binding ProductList}" SelectedItem="{Binding ProductSelected}" ItemDisplayBinding="{Binding ProductName}">   </Picker>

ViewModel

 public List<ProductModel> ProductList { get; set; }

Populating Data in Datasource in Viewmodel

    ProductList = Products.Result.ToList();

Getting Selected Data

   private object _ProductSelected;
      public object ProductSelected
    {
        get { return _ProductSelected; }
        set
        {
            _ProductSelected = value;
             ProductSelected_SelectedIndex.Execute(value);
             OnPropertyChanged("ProductSelected"); //in case you are using MVVM Light
        }
    }

 private Command ProductSelected_SelectedIndex
    {
        get
        {
            return new Command((e) =>
            {


          }}}



 private object _CitySelectedFromList;
    public object CitySelectedFromList
    {
        get { return _CitySelectedFromList; }
        set
        {
            _CitySelectedFromList = value;
            var cityid = _CitySelectedFromList as CityMasterModel;
            tempcityids = Convert.ToInt32(cityid.Id);

        }
    }

Upvotes: 0

lalit Maheshwari
lalit Maheshwari

Reputation: 144

you are binding view model before Initialise page so that is wrong thing we can not bind data without Initialise page fro that you need to change code of xaml.cs like below public EditGolfRoundPage (GolfRound round) { InitializeComponent (); BindingContext = editGolfRoundViewModel; BindingContext.GolfRound = round; }

that will work for you Happy Coding :)

Upvotes: 0

Related Questions