Nitrus Brio
Nitrus Brio

Reputation: 99

How to bind datepicker to viewModel?

How to get value from DatePicker and set it in variable in ViewModel? In my xaml file I have date picker like:

<DatePicker x:Name="dateTo"
    TextColor="White"
    FontSize="Small"
    Date="{Binding DateTo}"
    HorizontalOptions="StartAndExpand"
    VerticalOptions="CenterAndExpand"
    IsVisible="{Binding DateToPickerVisibility}"
    Margin="5,0,0,0"
    IsEnabled="False"/>

In my ViewModel I have property

public DateTime DateTo { get; set; }

and set it's value in InidData method:

DateTo = DateTime.Now.Date.AddDays(1); 

But how to change that value when date is changed and "OK" button on picker is clicked?

Upvotes: 1

Views: 3385

Answers (2)

Jessie Zhang -MSFT
Jessie Zhang -MSFT

Reputation: 13843

Yes, your ViewModel need to implement INotifyPropertyChanged,so that the DatePicker could update the value automatically.

There is a full demo which works properly. The main code is :

 public class DateViewModel: INotifyPropertyChanged
{
    bool _dateToPickerVisibility;

    public bool DateToPickerVisibility
    {
        set { SetProperty(ref _dateToPickerVisibility, value); }
        get { return _dateToPickerVisibility; }
    }

    DateTime _dateTo;
    public DateTime DateTo
    {
        set { SetProperty(ref _dateTo, value); }
        get { return _dateTo; }
    }

    public DateViewModel()
    {
        DateTo = DateTime.Now.Date.AddDays(1);
        DateToPickerVisibility = true;
    }

    bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
    {
        if (Object.Equals(storage, value))
            return false;

        storage = value;
        OnPropertyChanged(propertyName);
        return true;
    }

    protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

MainPage.xaml

 <StackLayout VerticalOptions="CenterAndExpand" HorizontalOptions="Start">
    <DatePicker x:Name="dateTo"
                FontSize="Small"
                Date="{Binding DateTo}"
                HorizontalOptions="StartAndExpand"
                VerticalOptions="Start"
                IsVisible="{Binding DateToPickerVisibility}"
                Margin="5,0,0,0"/>

    <Button x:Name="mButton" 
            Text="Hide DatePicker"
            Clicked="MButton_Clicked"
            VerticalOptions="Center"
            />
</StackLayout>

MainPage.xaml.cs

public partial class MainPage : ContentPage
 {
    DateViewModel dateViewModel;

    public MainPage()
    {
        InitializeComponent();
        dateViewModel = new DateViewModel();
        BindingContext = dateViewModel;

    }

    private void MButton_Clicked(object sender, EventArgs e)
    {
        if (dateViewModel.DateToPickerVisibility) {
            dateViewModel.DateToPickerVisibility = false;
            mButton.Text = "Make DatePicker visible";
        }
        else {
            dateViewModel.DateToPickerVisibility = true;
            mButton.Text = "Hide DatePicker";
        }
    }
}

Note:

1.You can init the value in the constructor of your ViewModel.e.g.

 public DateViewModel()
    {
        DateTo = DateTime.Now.Date.AddDays(1);
        DateToPickerVisibility = true;
    }

2.To make the datePicker visible or hidden, I added a Button to change the value of DateToPickerVisibility.

  private void MButton_Clicked(object sender, EventArgs e)
    {
        if (dateViewModel.DateToPickerVisibility) {
            dateViewModel.DateToPickerVisibility = false;
            mButton.Text = "Make DatePicker visible";
        }
        else {
            dateViewModel.DateToPickerVisibility = true;
            mButton.Text = "Hide DatePicker";
        }
    }

The result is :

enter image description here

Upvotes: 1

Brandon Minnick
Brandon Minnick

Reputation: 15340

Your XAML looks fine.

Your property in the ViewModel, however, isn't invoking PropertyChanged. When the value of a Property in the ViewModel changes, it needs to call PropertyChanged?.Invoke to alert/update the View.

Here's an example of the XAML, its Code-Behind and its ViewModel:

XAML

<DatePicker x:Name="dateTo"
    TextColor="White"
    FontSize="Small"
    Date="{Binding DateTo}"
    HorizontalOptions="StartAndExpand"
    VerticalOptions="CenterAndExpand"
    IsVisible="{Binding DateToPickerVisibility}"
    Margin="5,0,0,0"
    IsEnabled="False"/>

Code Behind

public partial class MyView
{
    InitializeComponent();
    BindingContext = new MyViewModel();
}

ViewModel

public class MyViewModel : INotifyPropertyChanged
{
    bool _dateToPickerVisibility
    DateTime _dateTo

    public event PropertyChangedEventHandler PropertyChanged;

    public DateTime DateTo
    {
        get => _dateTo;
        set
        {
            _dateTo = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(DateTo)));
        }
    }

    public bool DateToPickerVisibility
    {
        get => _dateToPickerVisibility;
        set 
        {
            _dateToPickerVisibility = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(DateToPickerVisibility)));
        }
    }
}

Upvotes: 0

Related Questions