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