Привязка трех свойств к ДатаПикеру

#xaml #xamarin #xamarin.forms #mvvm

Вопрос:

Как лучше всего привязать дату в DatePicker к чему — то подобному:

       "startedAt": {
        "year": 2021,
        "month": 9,
        "day": 11
      }
 

В json это выглядит так, но это будут три отдельных входа в свойствах c#. Мой класс записи, который я использую для своей наблюдаемой коллекции и класса даты:

 public class ListEntry : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

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

        public int? id { get; set; }
        public Media media { get; set; }
        public int? _score;

        public int? score
        {
            get => _score;
            set
            {
                if (value == _score)
                    return;

                _score = value;
                OnPropertyChanged();
            }
        }

        public int _Progress;
        public int progress
        {
            get => _Progress;
            set
            {
                if (value == _Progress)
                    return;

                _Progress = value;
                OnPropertyChanged();
            }
        }
        public string status { get; set; }
        public Date startedAt { get; set; }
    }

    public class Date : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

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

        public int? _year;

        public int? year
        {
            get => _year;
            set
            {
                if (value == _year)
                    return;

                _year = value;
                OnPropertyChanged();
            }
        }

        public int? _month;

        public int? month
        {
            get => _month;
            set
            {
                if (value == _month)
                    return;

                _month = value;
                OnPropertyChanged();
            }
        }
        public int? _day;
        public int? day
        {
            get => _day;
            set
            {
                if (value == _day)
                    return;

                _day = value;
                OnPropertyChanged();
            }
        }
    }
 

Чего мне нужно добиться, так это того, что при изменении даты в DatePicker эти три свойства тоже изменятся.

Я пробовал что-то подобное сам

 <DatePicker>
                            <DatePicker.Date>
                                <MultiBinding Mode="TwoWay" StringFormat="{}{0}/{1}/{2}">
                                    <Binding Path="startedAt.month" TargetNullValue="2" />
                                    <Binding Path="startedAt.day" TargetNullValue="3" />
                                    <Binding Path="startedAt.year" TargetNullValue="2000" />
                                </MultiBinding>
                            </DatePicker.Date>
                        </DatePicker>
 

Он правильно подбирает даты, но изменение одной из них не меняет свойств, и я получаю ошибки. И это кажется ошибочным, когда я прокручиваю страницу вниз и возвращаюсь к началу, она возвращается к исходной привязке вместо выбранной даты. Это не сработает, или я сделал это неправильно?

 [0:] MultiBinding: '/20/2021' cannot be converted to type 'System.DateTime'
[0:] MultiBinding: '//' cannot be converted to type 'System.DateTime'
[0:] MultiBinding: '/20/1998' cannot be converted to type 'System.DateTime'
[0:] MultiBinding: '//' cannot be converted to type 'System.DateTime'
[0:] MultiBinding: '/16/2021' cannot be converted to type 'System.DateTime'
[0:] MultiBinding: '//' cannot be converted to type 'System.DateTime'
[0:] MultiBinding: '/1/2021' cannot be converted to type 'System.DateTime'
[0:] MultiBinding: '//' cannot be converted to type 'System.DateTime'
[0:] MultiBinding: '/20/2021' cannot be converted to type 'System.DateTime'
[0:] MultiBinding: '//' cannot be converted to type 'System.DateTime'
[0:] MultiBinding: '/23/2021' cannot be converted to type 'System.DateTime'
[0:] MultiBinding: '//' cannot be converted to type 'System.DateTime'
[0:] MultiBinding: '/20/2021' cannot be converted to type 'System.DateTime'
[0:] MultiBinding: '//' cannot be converted to type 'System.DateTime'
 

Возможно, мне нужен какой-то преобразователь, и я действительно не могу менять классы, я думаю, он может не десериализоваться?

Редактировать:

                                         foreach (var Group in AnimeGroupObservable)
                {
                    foreach (var Entry in Group)
                    {
                        if (Entry.startedAt.year == null)
                        {
                            Entry.startedAt.Time = new DateTime(1970, 01, 01);
                        }
                        else
                        {
                            Entry.startedAt.Time = new DateTime((int)Entry.startedAt.year, (int)Entry.startedAt.month, (int)Entry.startedAt.day);
                        }

                    }
                }
 

Я добавил дату и время в свою модель

 public DateTime? _Time;
        public DateTime? Time
        {
            get => _Time;
            set
            {
                if (value == _Time)
                    return;

                _Time = value;
                OnPropertyChanged();
            }
        }
 

Комментарии:

1. было бы намного проще просто иметь свойство DateTime в вашей модели. Дата-время имеет свойства для Месяца/Дня/года, поэтому действительно ли необходимо объявлять свой собственный тип даты?

2. Потенциально я мог бы это сделать. Будет ли это эффективным циклическим перебором элементов для установки даты-времени? Поскольку я не могу изменить модель API, она не моя. Я работаю с тем, что у меня есть. Я отредактировал сообщение с помощью некоторого кода, который я сделал. Как я могу правильно обращаться со значениями null в этом случае? Даты могут быть пустыми из API. Я добавлял (int) перед каждой записью. Началось с того, что моя модель содержит свойства, допускающие значения null.

3. Добавьте свойство Datetime только для чтения, чтобы объединить эти три свойства в классе модели?

Ответ №1:

Вы можете попробовать использовать Завершенное событие в записи и Выбранное событие в ДатаПикере, чтобы установить связь между ними. Измените дату после изменения текста в записи и измените текст после выбранной даты. Вот моя примерная страница и код:

xmal:

 <StackLayout x:Name="stk"s/>
<Entry x:Name="E_Year" Completed="Entry Completed"/>
<Entry x:Name="E_ Month" Completed="Entry Completed"/>
<Entry x:Name="E_Day" Completed="Entry Completed"/>
<DatePicker x:Name"mydtp" DateSelected="0nDateSelected"/>
</StackLayout>
 

кодовая привязка:

 private void Entry _Completed(object sender, EventArgs e)
{

int _year = Convert. ToInt16(E_Year.Text);

int _month = Convert. ToInt16(E_Month.Text);

int _day = Convert.ToInt16(E_Day.Text);

DateTime _dateTime = new DateTime(_year,_month,_day);
mydtp.Date =_dateTime;
}

private void OnDateSelected (object sender, EventArgs e)
{
DateTime dateTime = mydtp.Date;

E_Year.Text = dateTime.Year.ToString();
E_Month.Text = dateTime Month.ToString();
E_Day.Text = dateTime.Day.ToString();

}