繁体   English   中英

我在 Xamarin.forms 中遇到数据绑定问题

[英]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 您将需要在其中添加更多属性,因为我很确定StartTimeMappingEndTimeMapping期望DateTime 但我可能错了。

希望这能让你走上正确的道路。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM