DataSource: Populating with Data

TKDataSource can consume data coming from various sources.

The simplest way to load data in TKDataSource is to use an array with numbers or strings:

self.dataSource = [[TKDataSource alloc] initWithArray:@[ @10, @5, @12, @7, @44 ]];
dataSource = TKDataSource(array: [ 10, 5, 12, 7, 44 ])
dataSource = new TKDataSource (ArrayWithObjects(new object [] { 10, 5, 12, 7, 44 }), null);

It also supports arrays of business objects. In this scenario you can use displayKey and valueKey properties to define how to present the data:

NSMutableArray *items = [NSMutableArray new];
[items addObject:[[DSItem alloc] initWithName:@"John" value:22.0 group:@"one"]];
[items addObject:[[DSItem alloc] initWithName:@"Peter" value:15.0 group:@"one"]];
[items addObject:[[DSItem alloc] initWithName:@"Abby" value:47.0 group:@"one"]];
[items addObject:[[DSItem alloc] initWithName:@"Robert" value:45.0 group:@"two"]];
[items addObject:[[DSItem alloc] initWithName:@"Alan" value:17.0 group:@"two"]];
[items addObject:[[DSItem alloc] initWithName:@"Saly" value:33.0 group:@"two"]];

self.dataSource.displayKey = @"name";
self.dataSource.valueKey = @"value";
self.dataSource.itemSource = items;
var items = [DSItem]()

items.append(DSItem(name: "John", value: 22, group: "one"))
items.append(DSItem(name: "Peter", value: 15, group: "one"))
items.append(DSItem(name: "Abby", value: 47, group: "one"))
items.append(DSItem(name: "Robert", value: 45, group: "two"))
items.append(DSItem(name: "Alan", value: 17, group: "two"))
items.append(DSItem(name: "Saly", value: 33, group: "two"))

self.dataSource.displayKey = "name"
self.dataSource.valueKey = "value"
self.dataSource.itemSource = items
var array = new NSMutableArray ();
array.Add (new DSItem () { Name = "John", Value = 22.0f, Group = "one" });
array.Add (new DSItem () { Name = "Peter", Value = 15.0f, Group = "one" });
array.Add (new DSItem () { Name = "Abby", Value = 47.0f, Group = "one" });
array.Add (new DSItem () { Name = "Robert", Value = 45.0f, Group = "two" });
array.Add (new DSItem () { Name = "Alan", Value = 17.0f, Group = "two" });
array.Add (new DSItem () { Name = "Saly", Value = 33.0f, Group = "two" });

dataSource.DisplayKey = "Name";
dataSource.ValueKey = "Value";
dataSource.ItemSource = array;

If a greater precision is necessary, you can implement the formatText block to define how the data will be presented:

[self.dataSource formatText:^NSString *(id item, TKDataSourceGroup *group) {
    DSItem *dsItem = (DSItem*)item;
    return [NSString stringWithFormat:@"%@ has %f points", dsItem.name, dsItem.value];
}];
dataSource.formatText { (item, group) -> String! in
    let dsItem = item as! DSItem
    return "\(dsItem.name) has \(dsItem.value) points"
}
dataSource.FormatText ((NSObject item, TKDataSourceGroup group) => {
    DSItem dsItem = (DSItem)item;
    return new NSString(string.Format("{0} has {1} points", dsItem.Name, dsItem.Value));
});

When using NSDictionary as a data provider for TKDataSource, its items property contains the keys collection of the dictionary and the itemSource property contains the dictionary itself. The following code manipulates the dictionary by applying sorting and filtering methods and then presents the data:

NSDictionary *dict = @{ @"John": @50, @"Abby": @33, @"Smith": @42, @"Peter": @28, @"Paula": @25 };
TKDataSource *dataSource = [[TKDataSource alloc] initWithItemSource:dict];
[dataSource sortWithKey:@"" ascending:YES];
[dataSource filter:^BOOL(id item) {
    return [dict[item] intValue] > 30;
}];
let dictionary:NSDictionary = [ "John": 50, "Abby": 33, "Smith": 42, "Peter": 28, "Paula": 25 ]
let dataSource = TKDataSource(itemSource: dictionary)
dataSource.sort(withKey: "", ascending: true)
dataSource.filter { (name) -> Bool in
    return (dictionary.object(forKey: name) as! Int) > 30
}
NSMutableDictionary dict = new NSMutableDictionary();
dict.Add (new NSString ("John"), NSObject.FromObject (50));
dict.Add (new NSString ("Abby"), NSObject.FromObject (33));
dict.Add (new NSString ("Smith"), NSObject.FromObject (42));
dict.Add (new NSString ("Peter"), NSObject.FromObject (28));
dict.Add (new NSString ("Paula"), NSObject.FromObject (25));

TKDataSource dataSource = new TKDataSource ();
dataSource.ItemSource = dict;
dataSource.SortWithKey ("", true);
dataSource.Filter ((NSObject item) => {
    return ((NSNumber)dict.ObjectForKey(item)).Int32Value > 30;
});

TKDataSource is handy when loading data from resources. With a simple method call it loads a JSON formatted file, parses its data and is ready to present or shape the data:

_photos = [[TKDataSource alloc] initWithDataFromJSONResource:@"PhotosWithNames" ofType:@"json" rootItemKeyPath:@"photos"];
self.photos.loadData(fromJSONResource: "PhotosWithNames", ofType: "json", rootItemKeyPath: "photos")
this.Photos = new TKDataSource ("PhotosWithNames", "json", "photos");

It can load also data coming from a web service. The following code downloads a JSON formatted data from a web service, groups its items and presents the result in TKChart:

TKChart *chart = [[TKChart alloc] initWithFrame:self.view.bounds];
chart.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[self.view addSubview:chart];

NSString *url = @"http://www.telerik.com/docs/default-source/ui-for-ios/weather.json?sfvrsn=2";
[self.dataSource loadDataFromURL:url dataFormat:TKDataSourceDataFormatJSON rootItemKeyPath:@"dayList" completion:^(NSError *error) {

    if (error) {
        NSLog(@"Can't connect with the server");
        return;
    }

    [self.dataSource.settings.chart createSeries:^TKChartSeries *(TKDataSourceGroup *group) {
        TKChartSeries *series = nil;
        if ([group.valueKey isEqualToString:@"clouds"]) {
            series = [TKChartColumnSeries new];
            series.yAxis = [[TKChartNumericAxis alloc] initWithMinimum:@0 andMaximum:@100];
            series.yAxis.title = @"clouds";
            series.yAxis.style.titleStyle.rotationAngle = M_PI_2;
        }
        else {
            series = [TKChartLineSeries new];
            series.yAxis = [[TKChartNumericAxis alloc] initWithMinimum:@-10 andMaximum:@30];
            if ([group.valueKey isEqualToString:@"temp.min"]) {
                series.yAxis.position = TKChartAxisPositionRight;
                series.yAxis.title = @"temperature";
                series.yAxis.style.titleStyle.rotationAngle = M_PI_2;
                [chart addAxis:series.yAxis];
            }
        }
        return series;
    }];

    [self.dataSource map:^id(id item) {
        NSTimeInterval interval = [[item valueForKey:@"dateTime"] doubleValue];
        NSDate *date = [NSDate dateWithTimeIntervalSince1970:interval];
        [item setValue:date forKey:@"dateTime"];
        return item;
    }];

    self.dataSource.valueKey = @"humidity";

    NSArray *items = self.dataSource.items;
    self.dataSource.itemSource = @[ [[TKDataSourceGroup alloc] initWithItems:items valueKey:@"clouds" displayKey:@"dateTime"],
                                    [[TKDataSourceGroup alloc] initWithItems:items valueKey:@"temp.min" displayKey:@"dateTime"],
                                    [[TKDataSourceGroup alloc] initWithItems:items valueKey:@"temp.max" displayKey:@"dateTime"] ];
    chart.dataSource = self.dataSource;

    NSDateFormatter *formatter = [NSDateFormatter new];
    formatter.dateFormat = @"dd";
    TKChartDateTimeAxis *xAxis = (TKChartDateTimeAxis*)chart.xAxis;
    xAxis.majorTickInterval = 1;
    xAxis.plotMode = TKChartAxisPlotModeBetweenTicks;
    xAxis.labelFormatter = formatter;
    xAxis.title = @"date";
    xAxis.minorTickIntervalUnit = TKChartDateTimeAxisIntervalUnitDays;
}];
let chart = TKChart(frame: self.view.bounds)
chart.autoresizingMask = UIViewAutoresizing(rawValue: ~UIViewAutoresizing().rawValue)
self.view.addSubview(chart)

let url = "http://www.telerik.com/docs/default-source/ui-for-ios/weather.json?sfvrsn=2"
dataSource.loadData(fromURL: url, dataFormat: TKDataSourceDataFormat.JSON, rootItemKeyPath: "dayList") { (err: Error?) -> Void in

    if err != nil {
        print("Can't connect with the server!")
        return
    }

    self.dataSource.settings.chart.createSeries { (group: TKDataSourceGroup?) -> TKChartSeries! in
        let series:TKChartSeries
        if group!.valueKey == "clouds" {
            series = TKChartColumnSeries()
            series.yAxis = TKChartNumericAxis(minimum: 0, andMaximum: 100)
            series.yAxis!.title = "clouds"
            series.yAxis!.style.titleStyle.rotationAngle = CGFloat(M_PI_2);
        }
        else {
            series = TKChartLineSeries()
            series.yAxis = TKChartNumericAxis(minimum: -10, andMaximum: 30)
            if group!.valueKey == "temp.min" {
                series.yAxis!.position = TKChartAxisPosition.right
                series.yAxis!.title = "temperature"
                series.yAxis!.style.titleStyle.rotationAngle = CGFloat(M_PI_2);
                chart.add(series.yAxis!)
            }
        }
        return series
    }

    self.dataSource.map {
        let interval = ($0 as AnyObject).value(forKey: "dateTime") as! TimeInterval
        let date = Date(timeIntervalSince1970: interval)
        ($0 as AnyObject).setValue(date, forKey: "dateTime")
        return $0
    }

    let items = self.dataSource.items
    self.dataSource.itemSource = [TKDataSourceGroup(items: items, valueKey: "clouds", displayKey: "dateTime"),
        TKDataSourceGroup(items: items, valueKey: "temp.min", displayKey: "dateTime"),
        TKDataSourceGroup(items: items, valueKey: "temp.max", displayKey: "dateTime")]

    chart.dataSource = self.dataSource

    let formatter = DateFormatter()
    formatter.dateFormat = "dd"
    let xAxis:TKChartDateTimeAxis = chart.xAxis as! TKChartDateTimeAxis
    xAxis.majorTickInterval = 1
    xAxis.setPlotMode(TKChartAxisPlotMode.betweenTicks)
    xAxis.labelFormatter = formatter
    xAxis.minorTickIntervalUnit = TKChartDateTimeAxisIntervalUnit.days
    xAxis.title = "date"
    xAxis.minorTickIntervalUnit = TKChartDateTimeAxisIntervalUnit.days
}
var chart = new TKChart (this.View.Bounds);
chart.AutoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleHeight;
this.View.Add (chart);

string url = "http://www.telerik.com/docs/default-source/ui-for-ios/weather.json?sfvrsn=2";
dataSource.LoadDataFromURL (url, TKDataSourceDataFormat.JSON, "dayList", (NSError err) => {
    if (err != null) {
        Console.WriteLine("Can't connect with the server!");
        return;
    }

    dataSource.Settings.Chart.CreateSeries((TKDataSourceGroup group) => {
        TKChartSeries series = null;
        if (group.ValueKey == "clouds") {
            series = new TKChartColumnSeries();
            series.YAxis = new TKChartNumericAxis(NSObject.FromObject(0), NSObject.FromObject(100));
            series.YAxis.Title = "clouds";
            series.YAxis.Style.TitleStyle.RotationAngle = (float)Math.PI/2.0f;
        }
        else {
            series = new TKChartLineSeries();
            series.YAxis = new TKChartNumericAxis(NSObject.FromObject(-10), NSObject.FromObject(30));
            if (group.ValueKey == "temp.min") {
                series.YAxis.Position = TKChartAxisPosition.Right;
                series.YAxis.Title = "temperature";
                series.YAxis.Style.TitleStyle.RotationAngle = (float)Math.PI/2.0f;
                chart.AddAxis(series.YAxis);
            }
        }
        return series;
    });

    dataSource.Map((NSObject item) => {
        double interval = ((NSNumber)item.ValueForKey(new NSString("dateTime"))).DoubleValue;
        NSDate date = NSDate.FromTimeIntervalSince1970(interval);
        item.SetValueForKey(date, new NSString("dateTime"));
        return item;
    });

    NSObject[] items = this.dataSource.Items;
    NSMutableArray newItems = new NSMutableArray();
    newItems.Add(new TKDataSourceGroup(items, "clouds", "dateTime"));
    newItems.Add(new TKDataSourceGroup(items, "temp.min", "dateTime"));
    newItems.Add(new TKDataSourceGroup(items, "temp.max", "dateTime"));
    dataSource.ItemSource = newItems;

    chart.DataSource = dataSource;

    var formatter = new NSDateFormatter();
    formatter.DateFormat = "dd";
    TKChartDateTimeAxis xAxis = (TKChartDateTimeAxis)chart.XAxis;
    xAxis.MajorTickInterval = 1;
    xAxis.PlotMode = TKChartAxisPlotMode.BetweenTicks;
    xAxis.LabelFormatter = formatter;
    xAxis.Title = "date";
    xAxis.MinorTickIntervalUnit = TKChartDateTimeAxisIntervalUnit.Days;
});