Stavrogin
Stavrogin

Reputation: 143

In Xamarin SelectedItem in Picker is empty even after selecting a value

In my Xamarin app, I'm loading banks information from database and trying to print the bank name in Picker.

It is working perfectly, thanks to this answer.

There is also a button, which check if there is no value selected, it will be disable and on selecting a value from picker, it will become enabled.

When I was using a static values in Picker it was working perfectly, but now, as I'm loading bank list and printing it in Picker, after selecting the value from Picker, still the button is disabled.

ViewModel.cs

load all banks into a list

var getBanks = await App.Database.GetBanksAsync();

foreach (var item in getBanks)
{
    _bankList.Add(item);
}

And then get the values in Picker

private ObservableCollection<Banks> _bankList = new ObservableCollection<Banks>();
public ObservableCollection<Banks> BankList
{
    get
    {
        return _bankList;
    }
    set
    {
        this.RaiseAndSetIfChanged(ref _bankList, value);
    }
}

private string _selectedBank;
public string SelectedBank
{
    get { return _selectedBank; }
    set
    {
        this.RaiseAndSetIfChanged(ref _selectedBank, value);
    }
}

Button Code

public ICommand SubmitCommand => new Command(async (submit) =>
{
    await NavigationService.NavigateToAsync<SuccessViewModel>();
}, (x) => false);

Views.xml

Pickers

<Picker 
    x:Name="picker_bank" 
    Title="Select Bank"
    ItemsSource="{Binding BankList}"
    ItemDisplayBinding="{Binding Name}"
    SelectedItem="{Binding SelectedBank}">
</Picker>

<Picker 
x:Name="picker_country" 
Title="Select a Country"
SelectedItem="{Binding SelectedCountry}">
        <Picker.ItemsSource>
            <x:Array Type="{x:Type x:String}">
                <x:String>Earth</x:String>
                <x:String>Mars</x:String>
            </x:Array>
        </Picker.ItemsSource>
</Picker>

Button Code

<Button 
x:Name="SubmitButton"
Text="Submit"
IsEnabled="False"
Command="{Binding SubmitCommand}">
    <Button.Triggers>
        <MultiTrigger TargetType="Button">
            <MultiTrigger.Conditions>
                <BindingCondition Binding="{Binding SelectedCountry,
                                   Converter={StaticResource stringNullOrEmptyValueBoolConverter }}" Value="false" />
                <BindingCondition Binding="{Binding SelectedBank,
                                   Converter={StaticResource stringNullOrEmptyValueBoolConverter }}" Value="false" />
            </MultiTrigger.Conditions>

            <Setter Property="IsEnabled" Value="True" />
        </MultiTrigger>
    </Button.Triggers>
</Button>

UPDATE

private Banks _selectedBank;
public Banks SelectedBank
{
    get { return _selectedBank; }
    set
    {
        this.RaiseAndSetIfChanged(ref _selectedBank, value);
    }
}
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
    if (value is Banks bank && bank.Name == null)
    {
        return true;
    }

    return false;
}

public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
    throw new NotImplementedException();
}

Upvotes: 0

Views: 1013

Answers (1)

Maharoz Alam Mugdho
Maharoz Alam Mugdho

Reputation: 466

Use The following code

private Bank _selectedBank;
  public Bank SelectedBank
  {
  get { return _selectedBank; }
    set
    {
        this.RaiseAndSetIfChanged(ref _selectedBank, value);
    }
}

Instead of

private string _selectedBank;
public string SelectedBank
{
    get { return _selectedBank; }
    set
    {
        this.RaiseAndSetIfChanged(ref _selectedBank, value);
    }
}

Explaination : When you are using static value thats fine, because SelectedBank property is correctly maaping to a string type.But when are using Bank object from database to populate picker, you have to use the type as Bank for the SelectedBank Property.

and also change the use of stringNullOrEmptyValueBoolConverter because it will not serve your purpose when you are using Bank object as selectedBank.

change your StringNullOrEmptyValueBoolConverter like this

public class StringNullOrEmptyValueBoolConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value is string)
            {
                if (string.IsNullOrEmpty(value as string))
                {
                    return false;
                }
                else
                {
                    return true;
                }
            }
            else
            {

                if (value == null)
                {
                    return false;
                }
                else
                {
                    return true;
                }
            }
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

Ignore the above/previous solution

First of all make your picker and button code like this

<Picker Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="3"
    x:Name="picker_bank" 
    Title="Select Bank"
    ItemsSource="{Binding BankList}"
    ItemDisplayBinding="{Binding Name}"
    SelectedItem="{Binding SelectedBank,,Mode=TwoWay}">
                        </Picker>

                        <Button Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="3"
x:Name="SubmitButton"
Text="Submit"
IsEnabled="{Binding IsButtonEnable}"
Command="{Binding SubmitCommand}"/>

now add IsButtonEnable property on your view model

protected bool _IsButtonEnable;
public bool IsButtonEnable
{
    get { return _IsButtonEnable; }
    set
    {
        SetProperty(ref _IsButtonEnable, value);
    }

}

on your selection change add this code

private Bank _SelectedBank;
        public Bank SelectedBank
        {
            get { return _SelectedBank; }
            set
            {
                _SelectedBank = value;
                if (SelectedBank != null)
                {
                    IsButtonEnable = true;
                }
                base.RaisePropertyChanged(nameof(SelectedBank));
            }
        }

hope in this way you can meet your desired output. here i also have added a video link where you can see the output of my solution watch the video here

hope my effort will take you to your desired solution.thank you.

Upvotes: 3

Related Questions