0

i have entry field and some pickers , The picker is a custom picker . When i enter some text into the entry field then click on the picker it fires twice , so when i click on an item the picker popup window remains and till i click cancel or select an item again. If i use the default picker the event fires like normal therefore i suspect it has nothing to do with the viewmodel binding . You may notice i have two pickers, it only happens with the first picker.

Could any point me in the right direction as to what i am doing wrong?

<StackLayout >
    <Grid >
        <Grid.RowDefinitions>
            <RowDefinition Height="50"/>
            <RowDefinition Height="25"/>
            <RowDefinition Height="40"/>
            <RowDefinition Height="35"/>
            <RowDefinition Height="40"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <Entry Text="" FontSize="16" Grid.Row="0" Grid.Column="0"
    Grid.ColumnSpan="2"/>
            <Label Text="Bedrooms:" Grid.Row="1" Grid.Column="0" 
 Grid.ColumnSpan="1" Style="{StaticResource entryLableStyle}"/>
        <autocomplete:RoundPicker x:Name="bedPicker"    Grid.Row="2"  
Grid.Column="0" Grid.ColumnSpan="1" ItemsSource="{Binding BedsList}"  
SelectedItem="{Binding BedSelected}"   ItemDisplayBinding="{Binding Name}"
 Style="{StaticResource pickerStyle}" />

        <Label Text="Min Price:" Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="1" Style="{StaticResource entryLableStyle}"/>
        <autocomplete:RoundPicker Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="1" ItemsSource="{Binding MaxPriceList}"  SelectedItem="{Binding MaxPriceSelected}"   ItemDisplayBinding="{Binding maxPrice}" Style="{StaticResource pickerStyle}"/>
    </Grid>
</StackLayout>

ViewModel:

public class TestViewModel : BaseViewModel
{
    public string BedsAmount { get; set; }
    public string MaxPrice { get; set; }
    public List<MaxPriceModel> MaxPriceList { get; set; }
    public List<Beds> BedsList { get; set; }
    private Beds _bedType;
    public Beds BedSelected
    {
        get
        {
            return _bedType;
        }
        set
        {
            if (_bedType != value)
            {
                _bedType = value;

                if (_bedType != null)
                {

                    BedsAmount = _bedType.Name;
                }
            }
        }
    }
    private MaxPriceModel _maxPriceSelected;
    public MaxPriceModel MaxPriceSelected
    {
        get
        {
            return _maxPriceSelected;
        }
        set
        {
            if (_maxPriceSelected != value)
            {
                _maxPriceSelected = value;

                if (_maxPriceSelected != null)
                {

                    MaxPrice = _maxPriceSelected.maxPrice;
                }
            }
        }
    }

    public class Beds
    {
        public string Name { get; set; }
    }

    public TestViewModel()
    {
        BedsList = GetBeds();
        MaxPriceList = GetMaxPrice();
    }

    public List<MaxPriceModel> GetMaxPrice()
    {
        var maxprice = new List<MaxPriceModel>()
      {
          new MaxPriceModel(){maxPrice = "100 000"},
          new MaxPriceModel(){maxPrice = "200 000"},
          new MaxPriceModel(){maxPrice = "300 000"},
          new MaxPriceModel(){maxPrice = "400 000"},
          new MaxPriceModel(){maxPrice = "500 000"},
          new MaxPriceModel(){maxPrice = "600 000"},
          new MaxPriceModel(){maxPrice = "700 000"},
          new MaxPriceModel(){maxPrice = "800 000"},
          new MaxPriceModel(){maxPrice = "900 000"},
          new MaxPriceModel(){maxPrice = "1 000 000"},
      };
        return maxprice;
    }
    public List<Beds> GetBeds()
    {
        var beds = new List<Beds>()
        {
            new Beds() { Name = "1" },
            new Beds() { Name = "2" },
            new Beds() { Name = "3" },
            new Beds() { Name = "4" },
            new Beds() { Name = "5" },
            new Beds() { Name = "6" },
            new Beds() { Name = "7" },
            new Beds() { Name = "8" },
            new Beds() { Name = "9" },
            new Beds() { Name = "10" },
        };
        return beds;
    }
}

Custom Renderer In App.Android

[assembly: ExportRenderer(typeof(RoundPicker),
typeof(RounndedPickerRenderAndroid))]


namespace PropertyApp.Droid.Models 
class RounndedPickerRenderAndroid : PickerRenderer
{
    private AlertDialog _dialog;
    IElementController ElementController => Element as IElementController;
    public RounndedPickerRenderAndroid(Context context) : base(context)
    {
    }
    protected override void
  OnElementChanged(ElementChangedEventArgs<Picker> e)
    {
        base.OnElementChanged(e);
        if (e.OldElement == null)
        {

            var gradientDrawable = new GradientDrawable();
            gradientDrawable.SetCornerRadius(0f);
            gradientDrawable.SetStroke(2, 
Android.Graphics.Color.LightGray);
            gradientDrawable.SetColor(Android.Graphics.Color.White);
            Control.SetBackground(gradientDrawable);
            Control.SetHintTextColor(Android.Graphics.Color.Gray);
            Control.SetPadding(20, 0, 0, 0);
            Control.SetSingleLine(true);

            Control.Click += Control_Click;
        }

    }

Content Page:

   namespace App.Views{[XamlCompilation(XamlCompilationOptions.Compile)]

 public partial class PickerTest : ContentPage
{
    private TestViewModel vm;
    public PickerTest ()
    {
        InitializeComponent ();

        vm = new TestViewModel();
        BindingContext = vm;
    }
  }
}



namespace App.Droid
{
[Activity(Label = "App", Icon = "@mipmap/icon", Theme = "@style/MainTheme", 
MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize |  
ConfigChanges.Orientation)]
public class MainActivity : 
global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
    protected override void OnCreate(Bundle savedInstanceState)
    {
        TabLayoutResource = Resource.Layout.Tabbar;
        ToolbarResource = Resource.Layout.Toolbar;

         FFImageLoading.Forms.Platform.CachedImageRenderer
.Init(enableFastRenderer: true);

        base.OnCreate(savedInstanceState);
        Rg.Plugins.Popup.Popup.Init(this, savedInstanceState);
        global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
        LoadApplication(new App(MultiMediaPickerService.SharedInstance));
        Xamarin.Essentials.Platform.Init(this, savedInstanceState);
    }


    public override void OnRequestPermissionsResult(int requestCode, string[]
 permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
    {
        Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode,
 permissions, grantResults);
          PermissionsImplementation.Current.
   OnRequestPermissionsResult(requestCode, 
   permissions, grantResults);
        base.OnRequestPermissionsResult(requestCode, permissions, 
  grantResults);
    }

    protected override void OnActivityResult(int requestCode, Result 
resultCode, Intent data)
    {
        base.OnActivityResult(requestCode, resultCode, data);
        MultiMediaPickerService.SharedInstance.OnActivityResult(requestCode,
 resultCode, data);
        base.OnActivityResult(requestCode, resultCode, data);

        if (requestCode == PickImageId)
        {
            if ((resultCode == Result.Ok) && (data != null))
            {
                // Set the filename as the completion of the Task
                PickImageTaskCompletionSource.SetResult(data.DataString);
            }
            else
            {
                PickImageTaskCompletionSource.SetResult(null);
            }
        }
    }

    public static MainActivity Current { private set; get; }

    public static readonly int PickImageId = 1000;

    public TaskCompletionSource<string> PickImageTaskCompletionSource { set; 
get; }


}

}

Custom Render:

using Android.Content;
using Android.Graphics.Drawables;
using App.Droid.Models;
using App.Helpers;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;

[assembly: ExportRenderer(typeof(RoundPicker),   
typeof(RounndedPickerRenderAndroid))]
 namespace App.Droid.Models
{
 class RounndedPickerRenderAndroid : PickerRenderer
{
    public RounndedPickerRenderAndroid(Context context) : base(context)
    {
    }
    protected override void OnElementChanged(ElementChangedEventArgs<Picker>
e)
    {
        base.OnElementChanged(e);
        if (e.OldElement == null)
        {
            var gradientDrawable = new GradientDrawable();
            gradientDrawable.SetCornerRadius(0f);
            gradientDrawable.SetStroke(2,
            Android.Graphics.Color.LightGray);
            gradientDrawable.SetColor(Android.Graphics.Color.White);
            Control.SetBackground(gradientDrawable);
            Control.SetHintTextColor(Android.Graphics.Color.Gray);
            Control.SetPadding(20, 0, 0, 0);
            Control.SetSingleLine(true); 

            Control.Click += Control_Click;
        }

    }
    protected override void Dispose(bool disposing)
    {
        Control.Click -= Control_Click;
        base.Dispose(disposing);
    }

    private void Control_Click(object sender, EventArgs e)
    {
        Picker model = Element;

        var picker = new NumberPicker(Context);
        if (model.Items != null && model.Items.Any())
        {
            // set style here
            picker.MaxValue = model.Items.Count - 1;
            picker.MinValue = 0;
            picker.SetBackgroundColor(Android.Graphics.Color.White);
            picker.SetDisplayedValues(model.Items.ToArray());
            picker.WrapSelectorWheel = false;
            picker.Value = model.SelectedIndex;
            picker.SetScrollIndicators(3);
            picker.DescendantFocusability = DescendantFocusability.BlockDescendants;
            picker.Visibility = ViewStates.Visible;

        }

        var layout = new LinearLayout(Context) { Orientation = Orientation.Vertical };
        layout.AddView(picker);
        ElementController.SetValueFromRenderer(VisualElement.IsFocusedProperty, true);

        var builder = new AlertDialog.Builder(Context);
        builder.SetView(layout);

        builder.SetTitle(model.Title ?? "");
        builder.SetNegativeButton("Cancel  ", (s, a) =>
        {
            ElementController.SetValueFromRenderer(VisualElement.IsFocusedProperty, false);
            // It is possible for the Content of the Page to be changed when Focus is changed.
            // In this case, we'll lose our Control.
            Control?.ClearFocus();
            _dialog = null;
        });
        builder.SetPositiveButton("Ok ", (s, a) =>
        {
            ElementController.SetValueFromRenderer(Picker.SelectedIndexProperty, picker.Value);
            // It is possible for the Content of the Page to be changed on SelectedIndexChanged.
            // In this case, the Element & Control will no longer exist.
            if (Element != null)
            {
                if (model.Items.Count > 0 && Element.SelectedIndex >= 0)
                    Control.Text = model.Items[Element.SelectedIndex];
                ElementController.SetValueFromRenderer(VisualElement.IsFocusedProperty, false);
                // It is also possible for the Content of the Page to be changed when Focus is changed.
                // In this case, we'll lose our Control.
                Control?.ClearFocus();
            }
            _dialog = null;
        });

        _dialog = builder.Create();
        _dialog.DismissEvent += (ssender, args) =>
        {
            ElementController?.SetValueFromRenderer(VisualElement.IsFocusedProperty, false);
        };
        _dialog.Show();
    }
  }
}
Anthony Horter
  • 45
  • 1
  • 12
  • What's the code in the Control_Click? I ran you code just now and it works well on my side. – nevermore Jun 13 '19 at 06:31
  • I do apologize i wasnt meant to paste that part of the code, without that control click and the function that goes with it it still fires twice. – Anthony Horter Jun 13 '19 at 06:54
  • I wrote a demo with your code and it works well. Can you check it:[picker-xamarin.forms](https://github.com/XfHua/picker-xamarin.forms). Any difference? – nevermore Jun 13 '19 at 07:00
  • I have tested yours and it works, Only difference being that i havent got my viewmodel and classes populated in the content page. – Anthony Horter Jun 13 '19 at 07:30
  • So can you share more code? I can't help you more with the code you post so far. – nevermore Jun 13 '19 at 07:58
  • I have edit my post and added my content page, My ViewModel is in a ViewModels folder and my Picker class is structured the same as yours its in a folder called Helpers. Otherwise there isnt much more to it. – Anthony Horter Jun 13 '19 at 08:07
  • The code you added is not enough. It's the same as mine. Any other difference? Or just share a simple sample which can reproduce the problem? Did you test it if you get rid of `Control.Click += Control_Click;`? Any difference in `autocomplete:RoundPicker`? – nevermore Jun 13 '19 at 08:14
  • I have added my Main Activity page form App.Android , other than that i cant see any other difference, I remade the app on a smaller scale and it is working correctly, Only difference is the main activity isnt the same. I just want to thank you for taking the time out to help me. I really appreciate it. – Anthony Horter Jun 13 '19 at 09:02
  • I did remove the Control_Click and it still didnt work – Anthony Horter Jun 13 '19 at 09:03
  • Not related with Main Activity. There must be something different in other place. Double check the code or share more code here so that we can help you. – nevermore Jun 13 '19 at 09:11
  • Can you please remove the custom renderer part of the picker and test again? Then you can find the problem is in custom renderer or xamarin.forms project. – nevermore Jun 13 '19 at 09:15
  • When i remove the custom render part it works. – Anthony Horter Jun 13 '19 at 09:27
  • Can you share all the code in your custom render? – nevermore Jun 13 '19 at 09:27
  • I have edit my post to included to Custom Renderer. – Anthony Horter Jun 13 '19 at 09:34
  • I mean **all** the code, these code won't cause the problem. Any other codes? Where is the Control_Click? Again, all the code in custom render. – nevermore Jun 13 '19 at 09:42
  • Sorry i deleted all the code with the control_click and it still didnt work but i have added it in again. Sorry for the inconvenience. – Anthony Horter Jun 13 '19 at 10:04
  • Why are you adding a new picker in control_click? This may cause the problem you described in your question. And you still did not give me all the code in custom render, what is ElementController, _dialog? Any other code? Can't reproduce your problem on my side with the code you post. – nevermore Jun 14 '19 at 06:02

0 Answers0