输入字段后自定义选择器触发两次

时间:2019-06-12 12:41:05

标签: c# xaml xamarin.forms picker custom-renderer

我有一个输入字段和一些选择器,该选择器是一个自定义选择器。 当我在输入字段中输入一些文本然后单击选择器时,它将触发两次,因此,当我单击一个项目时,选择器弹出窗口将保留,直到我单击“取消”或再次选择一个项目。如果我使用默认选择器,则事件会像正常情况一样触发,因此我怀疑它与viewmodel绑定无关。 您可能会注意到我有两个选择器,它仅在第一个选择器中发生。

关于我做错了什么,我可以指出正确的方向吗?

<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;
    }
}

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;
        }

    }

内容页面:

   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; }


}

}

自定义渲染:

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();
    }
  }
}

0 个答案:

没有答案