Home > Net >  Picker in Xamarin Forms ItemDisplayBinding not binding
Picker in Xamarin Forms ItemDisplayBinding not binding

Time:06-01

I'm writing a page in Xamarin, and I'm having issue binding to ItemDisplayBinding in the Picker. The code that I have is showing the main components of what I am trying to do to bind it. I am able to set ItemsSource="{Binding terms}" but if I try to set ItemDisplayBinding="{Binding Name}", Visual Studio says "Member not found in data context 'SearchViewModel' and the Picker is not being populated. All of the solutions I looked at haven't helped me to solve this.

My Term model (in the models folder):

namespace ClassSearch.Models
{
    public class Term
    {
        public string Code { get; set; }
        public string Name { get; set; }
        public Term(string code, string name)
        {
            Code = code;
            Name = name;
        }
    }
}

My ViewPage:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="ClassSearch.Views.SearchPage"
             xmlns:viewmodel="clr-namespace:ClassSearch.ViewModels"
             x:DataType="viewmodel:SearchViewModel"
             xmlns:ios="clr-namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core"
             ios:Page.UseSafeArea="True">
    <ContentPage.BindingContext>
        <viewmodel:SearchViewModel/>
    </ContentPage.BindingContext>
    <ContentPage.Content>
<Grid>
            <Grid.ColumnDefinitions>
                ...
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
               ...
            </Grid.RowDefinitions>
            
            <Frame Style="{StaticResource FrameStyle}" Grid.Column="1" Grid.ColumnSpan="2" Grid.Row="0">
            <Picker Title="Select" 
                    ItemsSource="{Binding Terms}"
                    IsEnabled="{Binding IsNotBusy}"
                    />
        </Frame>
 </Grid>
    </ContentPage.Content>
</ContentPage>

My view Model:

public class SearchViewModel : ViewModelBase
{
    public ObservableRangeCollection<Term> Terms { get; set; }
    public SearchViewModel()
    {
    Terms = new ObservableRangeCollection<Term>();
    }
    public async Task GetCurrentTerms()
    {
        IsBusy = true;
        Terms = Terms ?? await CurrentTerm.GetTerms();
        IsBusy = false;
    }
}

SearchPage.xaml.cs has the OnAppearing() overridden with

protected override async void OnAppearing()
    {
        base.OnAppearing();
        if (BindingContext is SearchViewModel vm)
        {
            await vm.GetCurrentTerms();
        }
     }

It appears this is the code causing the problem, but I don't see what the issue is.

public static class CurrentTerm
    {
        public static async Task<ObservableRangeCollection<Term>> GetTerms()
        {
            ObservableRangeCollection<Term> terms = new ObservableRangeCollection<Term>();
            //  YYYY/MM/DD
            DateTime currentDay = DateTime.Now.Date;
            DateTime SummerCheck = new DateTime(currentDay.Year, 11, 01);
            DateTime SpringCheck = new DateTime(currentDay.Year, 10, 01);
            DateTime FallCheck = new DateTime(currentDay.Year, 03, 01);
            if ((currentDay - SummerCheck).Days > 0)
            {
                var s = $"2{currentDay.Year % 100   1}4";
                var sp = $"2{currentDay.Year % 100   1}1";
                terms.Add(new Term(s, $"Summer {currentDay.Year   1}"));
                terms.Add(new Term(sp, $"Spring {currentDay.Year   1}"));
            }
            else if ((currentDay - SpringCheck).Days > 0)
            {
                var sp = $"2{currentDay.Year % 100   1}1";
                var f = $"2{currentDay.Year % 100}7";
                terms.Add(new Term(sp, $"Spring {currentDay.Year   1}"));
                terms.Add(new Term(f, $"Fall {currentDay.Year}"));
            }
            else if ((currentDay - FallCheck).Days > 0)
            {
                var f = $"2{currentDay.Year % 100}7";
                var s = $"2{currentDay.Year % 100}4";
                terms.Add(new Term(f, $"Fall {currentDay.Year}"));
                terms.Add(new Term(s, $"Summer {currentDay.Year}"));
            }
            return terms;
        }

    }

CodePudding user response:

Due to i do not have the CurrentTerm.GetTerms(), i make a sample with adding data directly in GetCurrentTerms method for your reference.

Xaml:

  <ContentPage.BindingContext>
    <viewmodel:SearchViewModel/>
</ContentPage.BindingContext>
<ContentPage.Content>
    <StackLayout>
        <Picker Title="Select" 
                ItemsSource="{Binding Terms}"
                ItemDisplayBinding="{Binding Name}"                    
                /> <!--IsEnabled="{Binding IsNotBusy}"-->
    </StackLayout>
</ContentPage.Content>

ViewModel:

public class SearchViewModel : ViewModelBase
{
    public ObservableRangeCollection<Term> Terms { get; set; }
    public SearchViewModel()
    {
        Terms = new ObservableRangeCollection<Term>();
    }
    public async Task GetCurrentTerms()
    {
        //IsBusy = true;
        //Terms = Terms ?? await CurrentTerm.GetTerms();
        //IsBusy = false;

        Term term1 = new Term("1", "a");
        Term term2 = new Term("2", "b");
        Term term3 = new Term("3", "c");
        Terms.Add(term1);
        Terms.Add(term2);
        Terms.Add(term3);
    }
}

enter image description here

Update:

Remove the code in OnAppearing. Set the data in ViewModel like below.

public static class CurrentTerm
{
    public static ObservableRangeCollection<Term> terms { get; set; }
    static CurrentTerm()
    {
        terms = new ObservableRangeCollection<Term>();
        //  YYYY/MM/DD
        DateTime currentDay = DateTime.Now.Date;
        DateTime SummerCheck = new DateTime(currentDay.Year, 11, 01);
        DateTime SpringCheck = new DateTime(currentDay.Year, 10, 01);
        DateTime FallCheck = new DateTime(currentDay.Year, 03, 01);
        if ((currentDay - SummerCheck).Days > 0)
        {
            var s = $"2{currentDay.Year % 100   1}4";
            var sp = $"2{currentDay.Year % 100   1}1";
            terms.Add(new Term(s, $"Summer {currentDay.Year   1}"));
            terms.Add(new Term(sp, $"Spring {currentDay.Year   1}"));
        }
        else if ((currentDay - SpringCheck).Days > 0)
        {
            var sp = $"2{currentDay.Year % 100   1}1";
            var f = $"2{currentDay.Year % 100}7";
            terms.Add(new Term(sp, $"Spring {currentDay.Year   1}"));
            terms.Add(new Term(f, $"Fall {currentDay.Year}"));
        }
        else if ((currentDay - FallCheck).Days > 0)
        {
            var f = $"2{currentDay.Year % 100}7";
            var s = $"2{currentDay.Year % 100}4";
            terms.Add(new Term(f, $"Fall {currentDay.Year}"));
            terms.Add(new Term(s, $"Summer {currentDay.Year}"));
        }
       
    }
}

ViewModel:

 public class SearchViewModel : ViewModelBase
{

    public ObservableRangeCollection<Term> Terms { get { return CurrentTerm.terms; } }
    public SearchViewModel()
    {

    }
    //public async Task GetCurrentTerms()
    //{
    //    //IsBusy = true;
    //    //Terms = Terms ?? await CurrentTerm.GetTerms();        
    //    //IsBusy = false;

    //    //Term term1 = new Term("1", "a");
    //    //Term term2 = new Term("2", "b");
    //    //Term term3 = new Term("3", "c");
    //    //Terms.Add(term1);
    //    //Terms.Add(term2);
    //    //Terms.Add(term3);
    //}
}

enter image description here

  • Related