mauicommunity-toolkit-mvvm

How can I intercept opening a picker in .Net MAUI?


I have a .Net MAUI app with CommunityToolkit.Mvvm.

Here is my picker:

                    <Picker Title="Choose Trowel Size..."
                        ItemsSource="{Binding TrowelCoveragesByUnit}"
                        ItemDisplayBinding="{Binding ThicknessText}"
                        SelectedItem="{Binding SelectedTrowelSize}"
                        Style="{StaticResource PickerStyle}"
                        Grid.Row="3" Grid.Column="1" />

This is in my page model:

    public List<TrowelCoverageByUnit> TrowelCoveragesByUnit =>
        TrowelCoverages.Select(tc => SelectedUnit.Code == "sqft" ?
        new TrowelCoverageByUnit(tc.ThicknessTextInches, tc.ThicknessValueInches, tc.Coverage) :
        new TrowelCoverageByUnit(tc.ThicknessTextMetric, tc.ThicknessValueMetric, tc.Coverage)).ToList();

    [ObservableProperty]
    [NotifyPropertyChangedFor(nameof(TrowelCoveragesByUnit))]
    [Required(ErrorMessage = "Unit of measure is required!")]
    private Unit _selectedUnit;

As we can see, if SelectedUnit property is null, TrowelCoveragesByUnit list is empty, and thus the picker is also empty. I need to avoid showing an empty list in the picker. Instead, if SelectedUnit is empty, I don't want the picker to open upon tap, rather, I need to display

Shell.Current.DisplayAlert("Unit of Measure Required", "Please select unit of measure first.", "OK");

Is it possible to do it, and if so, how?


Solution

  • According to Jason's suggestion, I added a transparent BoxView

                    <Label Text="Trowel Size (WxH):" Style="{StaticResource LabelEntryStyle}" Grid.Row="3" Grid.Column="0" />
                    <Picker x:Name="TrowelSizePicker"
                            Title="Choose Trowel Size..."
                            ItemsSource="{Binding TrowelCoveragesByUnit}"
                            ItemDisplayBinding="{Binding ThicknessText}"
                            SelectedItem="{Binding SelectedTrowelSize}"
                            Style="{StaticResource PickerStyle}"
                            Grid.Row="3" Grid.Column="1" />
    
                    <BoxView Grid.Row="3" Grid.Column="1"
                        Color="Transparent">
                        <BoxView.GestureRecognizers>
                            <TapGestureRecognizer Tapped="OnPickerTapped" />
                        </BoxView.GestureRecognizers>
                    </BoxView>
    

    And we handle the tap gesture in code behind:

    private async void OnPickerTapped(object sender, EventArgs e)
    {
        var viewModel = BindingContext as EstimatorAdhesiveInputPageModel;
        if (viewModel != null && viewModel.SelectedUnit == null)
        {
            await Shell.Current.DisplayAlert("Unit of Measure Required", "Please select unit of measure first.", "OK");
        }
        else
        {
            // Focus the picker to open it
            TrowelSizePicker.Focus();
        }
    }
    

    IMPORTANT: Make sure to use Color="Transparent" and not BackgroundColor="Transparent", which would give always black background.

    This works as expected. Though I would prefer using a command in the view model, but not sure it is possible with this approach.