[英]I'm having trouble with Data Binding in Xamarin.forms
对于一些上下文,我试图将我的视图链接到我的视图模型。 我的 model 中有一个 JSON 对象数组和另一个字符串。 我想在我的视图中显示这些对象,但是我在这样做时遇到了麻烦。
我的 Model:
namespace Timetabler.Models
{
public partial class Timetable
{
[JsonProperty("id")]
public long Id { get; set; }
[JsonProperty("nid")]
public long Nid { get; set; }
[JsonProperty("iid")]
public long Iid { get; set; }
[JsonProperty("lid")]
public long Lid { get; set; }
[JsonProperty("start")]
public double Start { get; set; }
[JsonProperty("dur")]
public double Dur { get; set; }
[JsonProperty("weeks")]
public string Weeks { get; set; }
[JsonProperty("day")]
public long Day { get; set; }
[JsonProperty("note", NullValueHandling = NullValueHandling.Ignore)]
public string Note { get; set; }
}
public partial struct TimetableElement
{
public long? Integer;
public string String;
public Timetable TimetableClass;
public static implicit operator TimetableElement(long Integer) => new TimetableElement { Integer = Integer };
public static implicit operator TimetableElement(string String) => new TimetableElement { String = String };
public static implicit operator TimetableElement(Timetable TimetableClass) => new TimetableElement { TimetableClass = TimetableClass };
}
public partial class Timetable
{
public static TimetableElement[][] FromJson(string json) => JsonConvert.DeserializeObject<TimetableElement[][]>(json, Converter.Settings);
}
public static class Serialize
{
public static string ToJson(this TimetableElement[][] self) => JsonConvert.SerializeObject(self, Converter.Settings);
}
internal static class Converter
{
public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
{
MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
DateParseHandling = DateParseHandling.None,
Converters =
{
TimetableElementConverter.Singleton,
new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }
},
};
}
internal class TimetableElementConverter : JsonConverter
{
public override bool CanConvert(Type t) => t == typeof(TimetableElement) || t == typeof(TimetableElement?);
public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer)
{
switch (reader.TokenType)
{
case JsonToken.Integer:
var integerValue = serializer.Deserialize<long>(reader);
return new TimetableElement { Integer = integerValue };
case JsonToken.String:
case JsonToken.Date:
var stringValue = serializer.Deserialize<string>(reader);
return new TimetableElement { String = stringValue };
case JsonToken.StartObject:
var objectValue = serializer.Deserialize<Timetable>(reader);
return new TimetableElement { TimetableClass = objectValue };
}
throw new Exception("Cannot unmarshal type TimetableElement");
}
public override void WriteJson(JsonWriter writer, object untypedValue, JsonSerializer serializer)
{
var value = (TimetableElement)untypedValue;
if (value.Integer != null)
{
serializer.Serialize(writer, value.Integer.Value);
return;
}
if (value.String != null)
{
serializer.Serialize(writer, value.String);
return;
}
if (value.TimetableClass != null)
{
serializer.Serialize(writer, value.TimetableClass);
return;
}
throw new Exception("Cannot marshal type TimetableElement");
}
public static readonly TimetableElementConverter Singleton = new TimetableElementConverter();
}
}
我的观点 Model:
namespace Timetabler.ViewModels
{
class TimetableViewModel : BaseViewModel
{
// First list in JSON data
public ObservableRangeCollection<TimetableElement> Names {get;}
// Second list in JSON data
public ObservableRangeCollection<TimetableElement> TypeOfClass {get;}
// Third list in JSON data
public ObservableRangeCollection<TimetableElement> Location {get;}
// Fourth list in JSON data
public ObservableRangeCollection<TimetableElement> Courses {get;}
public Command GetCoursesCommand { get; }
public Command GetNamesCommand { get; }
public TimetableViewModel()
{
Title = "Timetable";
// First list in JSON data
Names = new ObservableRangeCollection<TimetableElement>();
// Second list in JSON data
TypeOfClass = new ObservableRangeCollection<TimetableElement>();
// Third list in JSON data
Location = new ObservableRangeCollection<TimetableElement>();
// Fourth list in JSON data
Courses = new ObservableRangeCollection<TimetableElement>();
GetCoursesCommand = new Command(async () => await GetCoursesAsync());
GetNamesCommand = new Command(async () => await GetNamesAsync());
}
async Task GetNamesAsync()
{
if (IsBusy)
{
return;
}
try
{
IsBusy = true;
var timetableElements = await DataService.GetTimetablesAsync();
var names = timetableElements[0];
Names.ReplaceRange(names);
Title = $"Courses available({Names.Count}";
}
catch (Exception ex)
{
Debug.WriteLine($"Unable to get Names: {ex.Message}");
await Application.Current.MainPage.DisplayAlert("Error!", ex.Message, "OK");
}
finally
{
IsBusy = false;
}
}
async Task GetTypeOfClassAsync()
{
if (IsBusy)
{
return;
}
try
{
IsBusy = true;
var timetableElements = await DataService.GetTimetablesAsync();
var typeOfClass = timetableElements[1];
TypeOfClass.ReplaceRange(typeOfClass);
Title = $"Courses available({TypeOfClass.Count}";
}
catch (Exception ex)
{
Debug.WriteLine($"Unable to get TypeOfClass: {ex.Message}");
await Application.Current.MainPage.DisplayAlert("Error!", ex.Message, "OK");
}
finally
{
IsBusy = false;
}
}
async Task GetLocationsAsync()
{
if (IsBusy)
{
return;
}
try
{
IsBusy = true;
var timetableElements = await DataService.GetTimetablesAsync();
var location = timetableElements[2];
Location.ReplaceRange(location);
Title = $"Courses available({Courses.Count}";
}
catch (Exception ex)
{
Debug.WriteLine($"Unable to get Location: {ex.Message}");
await Application.Current.MainPage.DisplayAlert("Error!", ex.Message, "OK");
}
finally
{
IsBusy = false;
}
}
async Task GetCoursesAsync()
{
if (IsBusy)
{
return;
}
try
{
IsBusy = true;
var timetableElements = await DataService.GetTimetablesAsync();
var courses = timetableElements[3];
Courses.ReplaceRange(courses);
Title = $"Courses available({Courses.Count}";
}
catch (Exception ex)
{
Debug.WriteLine($"Unable to get courses: {ex.Message}");
await Application.Current.MainPage.DisplayAlert("Error!", ex.Message, "OK");
}
finally
{
IsBusy = false;
}
}
}
}
我的 model 将 JSON 反序列化为 C# 对象,此时我的 ViewModel 将它们分解为 ZA3CBC5Z4.166
我想在视图中显示这些对象。 该视图是一个 Syncfusion 时间表。 但在这一点上,我很高兴能够在列表视图中显示这些对象。 我似乎也无法解决这个问题。 我努力了:
我的观点
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:button="clr-namespace:Syncfusion.XForms.Buttons;assembly=Syncfusion.Buttons.XForms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:schedule="clr-namespace:Syncfusion.SfSchedule.XForms;assembly=Syncfusion.SfSchedule.XForms"
xmlns:viewmodel="clr-namespace:Timetabler.ViewModels"
mc:Ignorable="d"
Title="{Binding Title}"
x:Class="Timetabler.Views.TimetablePage">
<ContentPage.BindingContext>
<viewmodel:TimetableViewModel/>
</ContentPage.BindingContext>
<ContentPage.ToolbarItems>
<ToolbarItem Text="Add Course" Clicked="AddItem_Clicked" />
</ContentPage.ToolbarItems>
<schedule:SfSchedule x:Name="schedule"
ScheduleView ="WorkWeekView"
TimeIntervalHeight="130"
ShowCurrentTimeIndicator="True"
DataSource="{Binding Courses}">
<schedule:SfSchedule.ViewHeaderStyle>
<schedule:ViewHeaderStyle
BackgroundColor="#FFFFFF"
CurrentDayTextColor="#d1d119"
CurrentDateTextColor="#d1d119"
DayTextColor="#44453e"
DateTextColor="#44453e"
DayFontFamily="Arial"
DateFontFamily="Arial">
</schedule:ViewHeaderStyle>
</schedule:SfSchedule.ViewHeaderStyle>
</schedule:SfSchedule>
如您所见,我正在尝试绑定到我的 ViewModel 中的 Courses 属性。 难道我做错了什么? 我添加了 ContentPage。 BindingContext 作为正确的 ViewModel。 我如何能够从其中访问单个值?
据我所知,绑定没问题,但您使用的是自定义 object。 您不能指望SfScheduler
知道数据需要来自哪些字段。
如此处所述,您需要告诉它要在 object 中查找哪些字段,以确定开始和结束日期和时间等属性。 IE
<syncfusion:SfSchedule x:Name="schedule">
<syncfusion:SfSchedule.AppointmentMapping>
<syncfusion:ScheduleAppointmentMapping
ColorMapping="color"
EndTimeMapping="To"
StartTimeMapping="From"
SubjectMapping="EventName"
IsAllDayMapping="AllDay"/>
</syncfusion:SfSchedule.AppointmentMapping>
</syncfusion:SfSchedule>
查看您的TimetableElement
object 您将需要在其中添加更多属性,因为我很确定StartTimeMapping
和EndTimeMapping
期望DateTime
。 但我可能错了。
希望这能让你走上正确的道路。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.