Xamarin自定义DatePicker失去绑定

时间:2017-12-13 16:22:34

标签: c# android ios xamarin datepicker

我有这个自定义视图:

public class VolosDatePicker : Button {
    private DatePicker _Picker;
    private IViewContainer<View> _ParentLayout;

    public static readonly BindableProperty DateProperty = BindableProperty.Create(nameof(Date), typeof(DateTime?), typeof(VolosDatePicker));
    public DateTime? Date {
        get { return (DateTime?)GetValue(DateProperty); }
        set { SetValue(DateProperty, value); }
    }

    private string TextFormat = Utente.UteLoggato.formatoData;
    private string DefaultText = "click me";

    //public static readonly BindableProperty DefaultTextProperty = BindableProperty.Create<VolosDatePicker, string>(p => p.DefaultText, "Pick Date...");

    public VolosDatePicker() {
        //create the datepicker, make it invisible on the form.
        _Picker = new DatePicker {
            IsVisible = false
        };

        //handle the focus/unfocus or rather the showing and hiding of the dateipicker
        _Picker.Focused += _Picker_Focused;
        _Picker.Unfocused += _Picker_Unfocused;

        //command for the button
        Command = new Command((obj) => {
            //try to get the parent layout and add the datepicker
            if (_ParentLayout == null) {
                _ParentLayout = _GetParentLayout(Parent);
                if (_ParentLayout != null) {
                    //add the picker to the closest layout up the tree
                    _ParentLayout.Children.Add(_Picker);
                } else {
                    throw new InvalidOperationException("The DatePickerButton needs to be inside an Layout type control that can have other children");
                }
            }
            //show the picker modal
            _Picker.Focus();
        });
        _UpdateText();
    }

    private IViewContainer<View> _GetParentLayout(Element Parent) {
        //StackLayout, RelativeLayout, Grid, and AbsoluteLayout all implement IViewContainer,
        //it would be very rare that this method would return null.
        IViewContainer<View> parent = Parent as IViewContainer<View>;
        if (Parent == null) {
            return null;
        } else if (parent != null) {
            return parent;
        } else {
            return _GetParentLayout(Parent.Parent);
        }
    }

    void _Picker_Focused(object sender, FocusEventArgs e) {
        //default the date to now if Date is empty
        _Picker.Date = Date ?? DateTime.Now;
    }

    void _Picker_Unfocused(object sender, FocusEventArgs e) {
        //this always sets.. can't cancel the dialog.
        Date = _Picker.Date;
        _UpdateText();
    }

    protected override void OnBindingContextChanged() {
        base.OnBindingContextChanged();
        _UpdateText();
    }

    private void _UpdateText() {
        //the button has a default text, use that the first time.
        if (Date != null) {
            //default formatting is in the FormatProperty BindableProperty 
            base.Text = Date.Value.ToString(TextFormat);
        } else {
            base.Text = DefaultText;
        }
    }

    protected override void OnPropertyChanging(string propertyName = null) {
        //set this so there is an old date for the DateChangedEventArgs
        base.OnPropertyChanging(propertyName);
        if (propertyName == DateProperty.PropertyName) {
            //_OldDate = Date;
            _UpdateText();
            //if (_OldDate != null && Date != null) DateSelected(this, new DateChangedEventArgs((DateTime)_OldDate, (DateTime)Date));
        }
    }

    protected override void OnPropertyChanged(string propertyName = null) {
        base.OnPropertyChanged(propertyName);
        if (propertyName == DateProperty.PropertyName) {              
            _UpdateText();
        }
    }
}

在我的XAML页面中,我有这个绑定:

<view:VolosDatePicker Date="{Binding WoSpesaDett.DataSpesa}" Grid.Row="0" Grid.Column="1" />

我以这种方式设置了这个日期:

WoSpesaDett.DataSpesa = new System.DateTime(2015, 5, 18);
RaisePropertyChanged(() => WoSpesaDett);

在我使用此方法之前,DatePicker的日期值已正确设置,但在尝试使用控件选择器设置日期后,上述方法将停止工作。

如果我从控件选择器中选择任何日期,然后我尝试使用上述方法以编程方式设置日期,则日期不会更改。

它似乎失去了与属性WoSpesaDett.DataSpesa的绑定。

1 个答案:

答案 0 :(得分:1)

根据documentation

  

可选地,在创建BindableProperty实例时,可以指定以下参数:

     

绑定模式。这用于指定方向   财产价值变化将传播。在默认绑定模式下,   更改将从源传播到目标。

尝试将绑定模式设置为TwoWay,如下所示:

<view:VolosDatePicker Date="{Binding WoSpesaDett.DataSpesa, Mode=TwoWay}" Grid.Row="0" Grid.Column="1" />

或编辑BindableProperty本身。

希望它有所帮助!