├── SimpleDatabase
├── Resources
│ └── Resource.designer.cs
├── IPopulated.cs
├── SimpleDatabase.csproj
├── SqliteExtensions.cs
├── Model
│ └── Group.cs
└── SimpleDatabase.cs
├── Samples
├── iOS
│ ├── Assets.xcassets
│ │ ├── Contents.json
│ │ └── AppIcon.appiconset
│ │ │ └── Contents.json
│ ├── Entitlements.plist
│ ├── Main.cs
│ ├── AppDelegate.cs
│ ├── LaunchScreen.storyboard
│ ├── Info.plist
│ └── Sample.iOS.csproj
├── Droid
│ ├── Resources
│ │ ├── drawable
│ │ │ └── icon.png
│ │ ├── drawable-hdpi
│ │ │ └── icon.png
│ │ ├── drawable-xhdpi
│ │ │ └── icon.png
│ │ ├── drawable-xxhdpi
│ │ │ └── icon.png
│ │ ├── layout
│ │ │ ├── Toolbar.axml
│ │ │ └── Tabbar.axml
│ │ ├── values
│ │ │ └── styles.xml
│ │ └── AboutResources.txt
│ ├── Properties
│ │ ├── AndroidManifest.xml
│ │ └── AssemblyInfo.cs
│ ├── Assets
│ │ └── AboutAssets.txt
│ ├── MainActivity.cs
│ └── Sample.Droid.csproj
└── Sample
│ ├── ViewModels
│ ├── SongsViewModel.cs
│ └── ContactsViewModel.cs
│ ├── Pages
│ ├── SongsPage.xaml.cs
│ ├── ContactsPage.xaml.cs
│ ├── SongsPage.xaml
│ └── ContactsPage.xaml
│ ├── Model
│ ├── Song.cs
│ └── Person.cs
│ ├── Sample.shproj
│ ├── Data
│ ├── SongDatabase.cs
│ └── Database.cs
│ ├── App.cs
│ ├── Sample.projitems
│ └── SimpleDatabaseSource.cs
├── SimpleDatabase.iOS
├── Info.plist
└── SimpleDatabase.iOS.csproj
├── .gitignore
├── README.md
├── SimpleDatabase.sln
├── SimpleDatabase.nuspec
├── SimpleDatabase.Samples.sln
└── LICENSE
/SimpleDatabase/Resources/Resource.designer.cs:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Samples/iOS/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/Samples/Droid/Resources/drawable/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Clancey/SimpleDatabase/HEAD/Samples/Droid/Resources/drawable/icon.png
--------------------------------------------------------------------------------
/Samples/Droid/Resources/drawable-hdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Clancey/SimpleDatabase/HEAD/Samples/Droid/Resources/drawable-hdpi/icon.png
--------------------------------------------------------------------------------
/Samples/Droid/Resources/drawable-xhdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Clancey/SimpleDatabase/HEAD/Samples/Droid/Resources/drawable-xhdpi/icon.png
--------------------------------------------------------------------------------
/Samples/Droid/Resources/drawable-xxhdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Clancey/SimpleDatabase/HEAD/Samples/Droid/Resources/drawable-xxhdpi/icon.png
--------------------------------------------------------------------------------
/SimpleDatabase.iOS/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .droidres/
2 | /Make.config.local
3 | /.dist
4 | /.vs
5 | *~
6 | *.pidb
7 | *.userprefs
8 | *.resources
9 | bin/
10 | obj/
11 | .DS_Store
12 | test-results
13 | *.suo
14 | Components/
15 | [Pp]ackages
16 | *.nupkg
17 |
--------------------------------------------------------------------------------
/Samples/iOS/Entitlements.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/Samples/Sample/ViewModels/SongsViewModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | namespace Sample
3 | {
4 | public class SongsViewModel
5 | {
6 | public SimpleDatabaseSource Songs { get; set; } = new SimpleDatabaseSource (SongDatabase.Main);
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/SimpleDatabase/IPopulated.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace SimpleDatabase
7 | {
8 | public interface IPopulated
9 | {
10 | void Populated();
11 | }
12 | }
--------------------------------------------------------------------------------
/Samples/Sample/ViewModels/ContactsViewModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | namespace Sample
3 | {
4 | public class ContactsViewModel
5 | {
6 | public SimpleDatabaseSource Contacts { get; set; } = new SimpleDatabaseSource (Database.Main);
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/Samples/Sample/Pages/SongsPage.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | using Xamarin.Forms;
5 |
6 | namespace Sample
7 | {
8 | public partial class SongsPage : ContentPage
9 | {
10 | public SongsPage()
11 | {
12 | InitializeComponent();
13 | BindingContext = new SongsViewModel();
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Samples/Droid/Properties/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/Samples/Sample/Pages/ContactsPage.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | using Xamarin.Forms;
5 |
6 | namespace Sample
7 | {
8 | public partial class ContactsPage : ContentPage
9 | {
10 | public ContactsPage()
11 | {
12 | InitializeComponent();
13 | BindingContext = new ContactsViewModel();
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Samples/Droid/Resources/layout/Toolbar.axml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/Samples/Sample/Model/Song.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using SimpleDatabase;
3 | using SQLite;
4 |
5 | namespace Sample
6 | {
7 | public class Song
8 | {
9 | [PrimaryKey]
10 | public string Id { get; set; }
11 | public string Title {get;set;}
12 | [OrderBy]
13 | public string TitleNorm { get; set; }
14 | public string Artist {get;set;}
15 | [GroupBy]
16 | public string IndexCharacter { get; set; }
17 | }
18 | }
19 |
20 |
--------------------------------------------------------------------------------
/Samples/Droid/Resources/layout/Tabbar.axml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/Samples/iOS/Main.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 |
5 | using Foundation;
6 | using UIKit;
7 |
8 | namespace Sample.iOS
9 | {
10 | public class Application
11 | {
12 | // This is the main entry point of the application.
13 | static void Main(string[] args)
14 | {
15 | // if you want to use a different Application Delegate class from "AppDelegate"
16 | // you can specify it here.
17 | UIApplication.Main(args, null, "AppDelegate");
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Samples/Sample/Pages/SongsPage.xaml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/Samples/iOS/AppDelegate.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 |
5 | using Foundation;
6 | using UIKit;
7 |
8 | namespace Sample.iOS
9 | {
10 | [Register("AppDelegate")]
11 | public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
12 | {
13 | public override bool FinishedLaunching(UIApplication app, NSDictionary options)
14 | {
15 | global::Xamarin.Forms.Forms.Init();
16 |
17 | LoadApplication(new App());
18 |
19 | return base.FinishedLaunching(app, options);
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/Samples/Sample/Pages/ContactsPage.xaml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/Samples/Droid/Assets/AboutAssets.txt:
--------------------------------------------------------------------------------
1 | Any raw assets you want to be deployed with your application can be placed in
2 | this directory (and child directories) and given a Build Action of "AndroidAsset".
3 |
4 | These files will be deployed with your package and will be accessible using Android's
5 | AssetManager, like this:
6 |
7 | public class ReadAsset : Activity
8 | {
9 | protected override void OnCreate (Bundle bundle)
10 | {
11 | base.OnCreate (bundle);
12 |
13 | InputStream input = Assets.Open ("my_asset.txt");
14 | }
15 | }
16 |
17 | Additionally, some Android functions will automatically load asset files:
18 |
19 | Typeface tf = Typeface.CreateFromAsset (Context.Assets, "fonts/samplefont.ttf");
20 |
--------------------------------------------------------------------------------
/Samples/Droid/MainActivity.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | using Android.App;
4 | using Android.Content;
5 | using Android.Content.PM;
6 | using Android.Runtime;
7 | using Android.Views;
8 | using Android.Widget;
9 | using Android.OS;
10 |
11 | namespace Sample.Droid
12 | {
13 | [Activity(Label = "Sample.Droid", Icon = "@drawable/icon", Theme = "@style/MyTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
14 | public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
15 | {
16 | protected override void OnCreate(Bundle bundle)
17 | {
18 | TabLayoutResource = Resource.Layout.Tabbar;
19 | ToolbarResource = Resource.Layout.Toolbar;
20 |
21 | base.OnCreate(bundle);
22 |
23 | global::Xamarin.Forms.Forms.Init(this, bundle);
24 |
25 | LoadApplication(new App());
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/Samples/Sample/Sample.shproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {F2472651-1440-4A8B-B034-19BE2A507AF4}
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/Samples/Sample/Data/SongDatabase.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Net;
4 | using SimpleDatabase;
5 |
6 | namespace Sample
7 | {
8 | public class SongDatabase: SimpleDatabaseConnection
9 | {
10 | public SongDatabase () : base(dbPath)
11 | {
12 | CreateTable ();
13 | MakeClassInstant ();
14 | }
15 |
16 | static SongDatabase main;
17 | public static readonly string dbPath = Path.Combine (Environment.GetFolderPath (Environment.SpecialFolder.Personal), "music.db");
18 | public static SongDatabase Main
19 | {
20 | get{
21 | if (main == null)
22 | {
23 | downloadIfNeeded();
24 | main = new SongDatabase ();
25 |
26 | }
27 | return main;
28 | }
29 | }
30 | static void downloadIfNeeded()
31 | {
32 | if (File.Exists(dbPath))
33 | File.Delete(dbPath);
34 | return;
35 | //var client = new WebClient ();
36 | //client.DownloadFile ("https://www.dropbox.com/s/r25qjjae25mk29g/music.db", dbPath);
37 | }
38 |
39 | }
40 | }
41 |
42 |
43 |
--------------------------------------------------------------------------------
/Samples/Sample/Model/Person.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using SimpleDatabase;
3 | using SQLite;
4 |
5 | namespace Sample
6 | {
7 | public class Person
8 | {
9 | public Person ()
10 | {
11 | }
12 | [PrimaryKeyAttribute, AutoIncrement]
13 | public int Id {get;set;}
14 | public string FirstName {get;set;}
15 | [OrderByAttribute]
16 | public string MiddleName { get; set; }
17 | public string LastName { get; set; }
18 | string indexCharacter;
19 | [GroupBy]
20 | public string IndexCharacter {
21 | get {
22 | if(string.IsNullOrWhiteSpace(indexCharacter) && !string.IsNullOrWhiteSpace(LastName))
23 | indexCharacter = LastName.Substring(0, 1);
24 | return indexCharacter;
25 | }
26 | set { indexCharacter = value;}
27 | }
28 | public string Email { get; set; }
29 | public string PhoneNumber {get;set;}
30 | public string DisplayName => $"{LastName}, {FirstName}";
31 | public override string ToString ()
32 | {
33 | return string.Format ("{0} , {1}", LastName, FirstName);
34 | }
35 | }
36 | }
37 |
38 |
--------------------------------------------------------------------------------
/SimpleDatabase/SimpleDatabase.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard2.1;net6.0;net6.0-ios;net6.0-android;net6.0-maccatalyst
5 | SimpleDatabase
6 |
7 |
8 | TRACE;DEBUG;NETSTANDARD;NETSTANDARD2_1;CORE;
9 | preview
10 |
11 |
12 | TRACE;RELEASE;NETSTANDARD;NETSTANDARD2_1;CORE;
13 | preview
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/Samples/Droid/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using Android.App;
4 |
5 | // Information about this assembly is defined by the following attributes.
6 | // Change them to the values specific to your project.
7 |
8 | [assembly: AssemblyTitle("Sample.Droid")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("")]
13 | [assembly: AssemblyCopyright("(c) James Clancey")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
18 | // The form "{Major}.{Minor}.*" will automatically update the build and revision,
19 | // and "{Major}.{Minor}.{Build}.*" will update just the revision.
20 |
21 | [assembly: AssemblyVersion("1.0.0")]
22 |
23 | // The following attributes are used to specify the signing key for the assembly,
24 | // if desired. See the Mono documentation for more information about signing.
25 |
26 | //[assembly: AssemblyDelaySign(false)]
27 | //[assembly: AssemblyKeyFile("")]
28 |
--------------------------------------------------------------------------------
/Samples/Droid/Resources/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
24 |
27 |
28 |
--------------------------------------------------------------------------------
/Samples/iOS/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/Samples/iOS/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDisplayName
6 | SimpleDatabase
7 | CFBundleName
8 | SimpleDatabase
9 | CFBundleIdentifier
10 | com.companyname.sample
11 | CFBundleShortVersionString
12 | 1.0
13 | CFBundleVersion
14 | 1.0
15 | LSRequiresIPhoneOS
16 |
17 | MinimumOSVersion
18 | 8.0
19 | UIDeviceFamily
20 |
21 | 1
22 | 2
23 |
24 | UILaunchStoryboardName
25 | LaunchScreen
26 | UIRequiredDeviceCapabilities
27 |
28 | armv7
29 |
30 | UISupportedInterfaceOrientations
31 |
32 | UIInterfaceOrientationPortrait
33 | UIInterfaceOrientationLandscapeLeft
34 | UIInterfaceOrientationLandscapeRight
35 |
36 | UISupportedInterfaceOrientations~ipad
37 |
38 | UIInterfaceOrientationPortrait
39 | UIInterfaceOrientationPortraitUpsideDown
40 | UIInterfaceOrientationLandscapeLeft
41 | UIInterfaceOrientationLandscapeRight
42 |
43 | XSAppIconAssets
44 | Assets.xcassets/AppIcon.appiconset
45 |
46 |
47 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Simple Database
2 | ================
3 |
4 | Creating fast, responsive and grouped Tableviews is hard. Espcially with very large data sets. Simple Database takes care of this for you by extending [SQLite-net](https://github.com/praeclarum/sqlite-net)
5 |
6 | Available on Nuget
7 | ================
8 |
9 | https://www.nuget.org/packages/Clancey.SimpleDatabase/
10 |
11 |
12 | API
13 | ================
14 |
15 | Simple tables gives you the interface you need to populate a ListView
16 |
17 | ```cs
18 | Database.Main.RowsInSection(section);
19 |
20 | Database.Main.NumberOfSections();
21 |
22 | Database.Main.ObjectForRow(section, row);
23 |
24 | Database.Main.SectionHeader(section);
25 |
26 | Database.Main.QuickJump();
27 |
28 | ```
29 |
30 | Model Attributes
31 | ===
32 | Add attributes for OrderBy and Grouping
33 |
34 | ```cs
35 |
36 | class MyClass
37 | {
38 | [Indexed, PrimaryKey]
39 | public string Id {get;set;}
40 |
41 | //Typically this is just one letter, and the first letter of the displayed text
42 | [GroupBy]
43 | public virtual string IndexCharacter {get;set;}
44 |
45 | [OrderBy]
46 | public string Name {get;set;}
47 | }
48 | ```
49 |
50 |
51 | GroupInfo
52 | ================
53 |
54 | Sometimes you need to filter or Add dynamically compose a query. Simple Auth uses named parameters
55 |
56 | ```cs
57 | var artist = new { Id = "Foo"};
58 | var group = Database.Main.GetGroupInfo().Clone();
59 | group.Filter = "ArtistId = @ArtistId";
60 | group.Params["@ArtistId"] = artist.Id;
61 |
62 | Database.Main.RowsInSection(group , section);
63 |
64 | ```
65 |
66 | #Open Source Software
67 | This project was built on the shoulders of giants!
68 |
69 | - [SQLite-net](https://github.com/praeclarum/sqlite-net)
70 |
--------------------------------------------------------------------------------
/SimpleDatabase.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 14
4 | VisualStudioVersion = 14.0.25420.1
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimpleDatabase", "SimpleDatabase\SimpleDatabase.csproj", "{4FE40048-B716-42ED-9E26-C114689BAAFD}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimpleDatabase.iOS", "SimpleDatabase.iOS\SimpleDatabase.iOS.csproj", "{E8B052D6-9C21-4B3F-9520-29D7B38513C5}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|Any CPU = Debug|Any CPU
13 | Release|Any CPU = Release|Any CPU
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {4FE40048-B716-42ED-9E26-C114689BAAFD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
17 | {4FE40048-B716-42ED-9E26-C114689BAAFD}.Debug|Any CPU.Build.0 = Debug|Any CPU
18 | {4FE40048-B716-42ED-9E26-C114689BAAFD}.Release|Any CPU.ActiveCfg = Release|Any CPU
19 | {4FE40048-B716-42ED-9E26-C114689BAAFD}.Release|Any CPU.Build.0 = Release|Any CPU
20 | {E8B052D6-9C21-4B3F-9520-29D7B38513C5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21 | {E8B052D6-9C21-4B3F-9520-29D7B38513C5}.Debug|Any CPU.Build.0 = Debug|Any CPU
22 | {E8B052D6-9C21-4B3F-9520-29D7B38513C5}.Release|Any CPU.ActiveCfg = Release|Any CPU
23 | {E8B052D6-9C21-4B3F-9520-29D7B38513C5}.Release|Any CPU.Build.0 = Release|Any CPU
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | GlobalSection(MonoDevelopProperties) = preSolution
29 | StartupItem = InstantSample\InstantiOSSample.csproj
30 | EndGlobalSection
31 | EndGlobal
32 |
--------------------------------------------------------------------------------
/Samples/Sample/Data/Database.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading.Tasks;
3 | using System.Collections.Generic;
4 | using System.IO;
5 | using SimpleDatabase;
6 | using System.Net;
7 |
8 | namespace Sample
9 | {
10 | public class Database : SimpleDatabaseConnection
11 | {
12 | public Database () : this(dbPath)
13 | {
14 | }
15 | public Database(string path) : base(path)
16 | {
17 | CreateTable();
18 | }
19 |
20 | static Database main;
21 | public static readonly string dbPath = Path.Combine (Environment.GetFolderPath(Environment.SpecialFolder.Personal), "contacts.db");
22 |
23 | public static Database Main {
24 | get {
25 | if (main == null)
26 | main = new Database ();
27 | return main;
28 | }
29 | }
30 |
31 | public Task InsertPeople (List people)
32 | {
33 | return Task.Factory.StartNew (delegate {
34 |
35 | this.InsertAll (people);
36 | });
37 | }
38 |
39 | public static Task SetDatabase1000()
40 | {
41 | return DownloadDAtabase("https://www.dropbox.com/s/kob54oioz56rsnb/contacts-1000.db?dl=1", "contacts-1000.db");
42 |
43 | }
44 |
45 | public static Task SetDatabase10000()
46 | {
47 | return DownloadDAtabase("https://www.dropbox.com/s/llxh3zafm16lcrr/contacts-10000.db?dl=1", "contacts-10000.db");
48 |
49 | }
50 |
51 | public static Task SetDatabase20000()
52 | {
53 | return DownloadDAtabase("https://www.dropbox.com/s/foyjdl9yv894ssx/contacts-20000.db?dl=1", "contacts-20000.db");
54 | }
55 |
56 | static async Task DownloadDAtabase(string url, string database)
57 | {
58 | var path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), database);
59 | if (!File.Exists(path))
60 | {
61 | var client = new WebClient();
62 | await client.DownloadFileTaskAsync(url, path);
63 | }
64 | main = new Database(path);
65 | }
66 | }
67 | }
68 |
69 |
--------------------------------------------------------------------------------
/Samples/Droid/Resources/AboutResources.txt:
--------------------------------------------------------------------------------
1 | Images, layout descriptions, binary blobs and string dictionaries can be included
2 | in your application as resource files. Various Android APIs are designed to
3 | operate on the resource IDs instead of dealing with images, strings or binary blobs
4 | directly.
5 |
6 | For example, a sample Android app that contains a user interface layout (main.axml),
7 | an internationalization string table (strings.xml) and some icons (drawable-XXX/icon.png)
8 | would keep its resources in the "Resources" directory of the application:
9 |
10 | Resources/
11 | drawable/
12 | icon.png
13 |
14 | layout/
15 | main.axml
16 |
17 | values/
18 | strings.xml
19 |
20 | In order to get the build system to recognize Android resources, set the build action to
21 | "AndroidResource". The native Android APIs do not operate directly with filenames, but
22 | instead operate on resource IDs. When you compile an Android application that uses resources,
23 | the build system will package the resources for distribution and generate a class called "R"
24 | (this is an Android convention) that contains the tokens for each one of the resources
25 | included. For example, for the above Resources layout, this is what the R class would expose:
26 |
27 | public class R {
28 | public class drawable {
29 | public const int icon = 0x123;
30 | }
31 |
32 | public class layout {
33 | public const int main = 0x456;
34 | }
35 |
36 | public class strings {
37 | public const int first_string = 0xabc;
38 | public const int second_string = 0xbcd;
39 | }
40 | }
41 |
42 | You would then use R.drawable.icon to reference the drawable/icon.png file, or R.layout.main
43 | to reference the layout/main.axml file, or R.strings.first_string to reference the first
44 | string in the dictionary file values/strings.xml.
45 |
--------------------------------------------------------------------------------
/Samples/Sample/App.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading.Tasks;
3 | using Xamarin.Forms;
4 |
5 | namespace Sample
6 | {
7 | public class App : Application
8 | {
9 | ActivityIndicator spinner;
10 | public App()
11 | {
12 | spinner = new ActivityIndicator();
13 | // The root page of your application
14 | var content = new ContentPage
15 | {
16 | Title = "Sample",
17 | Content = new TableView(
18 | new TableRoot {
19 | new TableSection("Download database"){
20 | CreateCell("1,000 people",async ()=>{
21 | await SetupDatabase(Database.SetDatabase1000());
22 | }),
23 | CreateCell("10,000 people",async ()=>{
24 | await SetupDatabase(Database.SetDatabase10000());
25 | }),
26 | CreateCell("20,000 people",async ()=>{
27 | await SetupDatabase(Database.SetDatabase20000());
28 | }),
29 | new ViewCell{
30 | View = spinner,
31 | },
32 | },
33 | }
34 | ),
35 | };
36 |
37 | MainPage = new NavigationPage(content);
38 | }
39 |
40 | TextCell CreateCell(string text, Action action)
41 | {
42 | var cell = new TextCell
43 | {
44 | Text = text,
45 | };
46 | cell.Tapped += (sender, e) => action?.Invoke();
47 | return cell;
48 | }
49 | async Task SetupDatabase(Task setupDatabase)
50 | {
51 | spinner.IsRunning = true;
52 | try
53 | {
54 | await setupDatabase;
55 | await MainPage.Navigation.PushAsync(new ContactsPage());
56 |
57 | }
58 | catch (Exception ex)
59 | {
60 | this.MainPage.DisplayAlert("Error", ex.Message, "Ok");
61 | }
62 | finally
63 | {
64 | spinner.IsRunning = false;
65 | }
66 | }
67 |
68 | protected override void OnStart()
69 | {
70 | // Handle when your app starts
71 | }
72 |
73 | protected override void OnSleep()
74 | {
75 | // Handle when your app sleeps
76 | }
77 |
78 | protected override void OnResume()
79 | {
80 | // Handle when your app resumes
81 | }
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/Samples/Sample/Sample.projitems:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | $(MSBuildAllProjects);$(MSBuildThisFileFullPath)
5 | true
6 | {F2472651-1440-4A8B-B034-19BE2A507AF4}
7 |
8 |
9 | Sample
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | ContactsPage.xaml
20 |
21 |
22 | SongsPage.xaml
23 |
24 |
25 |
26 |
27 |
28 |
29 | MSBuild:UpdateDesignTimeXaml
30 |
31 |
32 | MSBuild:UpdateDesignTimeXaml
33 |
34 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/SimpleDatabase.nuspec:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Clancey.SimpleDatabase
5 | 1.1.6
6 | Clancey
7 | https://github.com/Clancey/SimpleDatabase/blob/master/LICENSE
8 | https://github.com/Clancey/SimpleDatabase
9 | false
10 | The fastest way to group large data sets for mobile
11 | SimpleDatabase is built on top of Sqlite-Net. It gives you everything you need to build fast grouped TableViews in Xamarin
12 | Updated Nugets
13 | James Clancey
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/SimpleDatabase.iOS/SimpleDatabase.iOS.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | AnyCPU
6 | {E8B052D6-9C21-4B3F-9520-29D7B38513C5}
7 | {FEACFBD2-3405-455C-9665-78FE426C6842};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
8 | Library
9 | SimpleDatabase
10 | Resources
11 | SimpleDatabase
12 | 8.0.30703
13 | 2.0
14 |
15 |
16 | True
17 | full
18 | False
19 | bin\Debug
20 | DEBUG;iOS
21 | prompt
22 | 4
23 | False
24 | true
25 | true
26 |
27 |
28 | none
29 | True
30 | bin\Release
31 | prompt
32 | 4
33 | False
34 | iOS
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 | IPopulated.cs
54 |
55 |
56 | SimpleDatabase.cs
57 |
58 |
59 | SqliteExtensions.cs
60 |
61 |
62 | Model\Group.cs
63 |
64 |
65 |
66 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/SimpleDatabase/SqliteExtensions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections;
3 | using System.Collections.Generic;
4 | using System.Diagnostics;
5 | using System.Threading.Tasks;
6 |
7 | namespace SQLite
8 | {
9 | public static class SqliteExtensions
10 | {
11 | public static Dictionary CreateTables(this SQLiteConnection connection, params Type[] types)
12 | {
13 | //CreateTablesResult Result has internal constructor
14 | var results = new Dictionary();
15 | foreach (Type type in types)
16 | {
17 | try
18 | {
19 | var aResult = connection.CreateTable(type);
20 | results[type] = aResult;
21 | }
22 | catch (Exception)
23 | {
24 | Debug.WriteLine("Error creating table for {0}", type);
25 | throw;
26 | }
27 | }
28 |
29 | return results;
30 | }
31 |
32 | public static int Delete(this SQLiteConnection connection, object objectToDelete, Type type)
33 | {
34 | var map = connection.GetMapping(type);
35 | var pk = map.PK;
36 | if (pk == null)
37 | {
38 | throw new NotSupportedException("Cannot delete " + map.TableName + ": it has no PK");
39 | }
40 | var q = $"delete from \"{map.TableName}\" where \"{pk.Name}\" = ?";
41 | var count = connection.Execute(q, pk.GetValue(objectToDelete));
42 |
43 | return count;
44 | }
45 |
46 | public static int InsertOrReplaceAll( this SQLiteConnection connection, IEnumerable objects, bool runInTransaction = true)
47 | {
48 | var c = 0;
49 | if (runInTransaction)
50 | {
51 | connection.RunInTransaction(() =>
52 | {
53 | foreach (var r in objects)
54 | {
55 | c += connection.InsertOrReplace(r);
56 | }
57 | });
58 | }
59 | else
60 | {
61 | foreach (var r in objects)
62 | {
63 | c += connection.InsertOrReplace(r);
64 | }
65 | }
66 | return c;
67 | }
68 |
69 | public static int InsertOrReplaceAll(this SQLiteConnection connection, IEnumerable objects, Type objType, bool runInTransaction = true)
70 | {
71 | var c = 0;
72 | if (runInTransaction)
73 | {
74 | connection.RunInTransaction(() =>
75 | {
76 | foreach (var r in objects)
77 | {
78 | c += connection.InsertOrReplace(r, objType);
79 | }
80 | });
81 | }
82 | else
83 | {
84 | foreach (var r in objects)
85 | {
86 | c += connection.InsertOrReplace(r);
87 | }
88 | }
89 | return c;
90 | }
91 |
92 | public static int DeleteAll(this SQLiteConnection connection, IEnumerable objects)
93 | {
94 | var c = 0;
95 | connection.RunInTransaction(() =>
96 | {
97 | foreach (var r in objects)
98 | {
99 | c += connection.Delete(r);
100 | }
101 | });
102 | return c;
103 | }
104 | public static int DeleteAll(this SQLiteConnection connection, IEnumerable objects, Type type)
105 | {
106 | var c = 0;
107 | connection.RunInTransaction(() =>
108 | {
109 | foreach (var r in objects)
110 | {
111 | c += connection.Delete(r, type);
112 | }
113 | });
114 | return c;
115 | }
116 |
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/Samples/iOS/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images": [
3 | {
4 | "idiom": "iphone",
5 | "size": "29x29",
6 | "scale": "1x"
7 | },
8 | {
9 | "idiom": "iphone",
10 | "size": "29x29",
11 | "scale": "2x"
12 | },
13 | {
14 | "idiom": "iphone",
15 | "size": "29x29",
16 | "scale": "3x"
17 | },
18 | {
19 | "idiom": "iphone",
20 | "size": "40x40",
21 | "scale": "2x"
22 | },
23 | {
24 | "idiom": "iphone",
25 | "size": "40x40",
26 | "scale": "3x"
27 | },
28 | {
29 | "idiom": "iphone",
30 | "size": "57x57",
31 | "scale": "1x"
32 | },
33 | {
34 | "idiom": "iphone",
35 | "size": "57x57",
36 | "scale": "2x"
37 | },
38 | {
39 | "idiom": "iphone",
40 | "size": "60x60",
41 | "scale": "2x"
42 | },
43 | {
44 | "idiom": "iphone",
45 | "size": "60x60",
46 | "scale": "3x"
47 | },
48 | {
49 | "idiom": "ipad",
50 | "size": "29x29",
51 | "scale": "1x"
52 | },
53 | {
54 | "idiom": "ipad",
55 | "size": "29x29",
56 | "scale": "2x"
57 | },
58 | {
59 | "idiom": "ipad",
60 | "size": "40x40",
61 | "scale": "1x"
62 | },
63 | {
64 | "idiom": "ipad",
65 | "size": "40x40",
66 | "scale": "2x"
67 | },
68 | {
69 | "idiom": "ipad",
70 | "size": "50x50",
71 | "scale": "1x"
72 | },
73 | {
74 | "idiom": "ipad",
75 | "size": "50x50",
76 | "scale": "2x"
77 | },
78 | {
79 | "idiom": "ipad",
80 | "size": "72x72",
81 | "scale": "1x"
82 | },
83 | {
84 | "idiom": "ipad",
85 | "size": "72x72",
86 | "scale": "2x"
87 | },
88 | {
89 | "idiom": "ipad",
90 | "size": "76x76",
91 | "scale": "1x"
92 | },
93 | {
94 | "idiom": "ipad",
95 | "size": "76x76",
96 | "scale": "2x"
97 | },
98 | {
99 | "size": "24x24",
100 | "idiom": "watch",
101 | "scale": "2x",
102 | "role": "notificationCenter",
103 | "subtype": "38mm"
104 | },
105 | {
106 | "size": "27.5x27.5",
107 | "idiom": "watch",
108 | "scale": "2x",
109 | "role": "notificationCenter",
110 | "subtype": "42mm"
111 | },
112 | {
113 | "size": "29x29",
114 | "idiom": "watch",
115 | "role": "companionSettings",
116 | "scale": "2x"
117 | },
118 | {
119 | "size": "29x29",
120 | "idiom": "watch",
121 | "role": "companionSettings",
122 | "scale": "3x"
123 | },
124 | {
125 | "size": "40x40",
126 | "idiom": "watch",
127 | "scale": "2x",
128 | "role": "appLauncher",
129 | "subtype": "38mm"
130 | },
131 | {
132 | "size": "44x44",
133 | "idiom": "watch",
134 | "scale": "2x",
135 | "role": "longLook",
136 | "subtype": "42mm"
137 | },
138 | {
139 | "size": "86x86",
140 | "idiom": "watch",
141 | "scale": "2x",
142 | "role": "quickLook",
143 | "subtype": "38mm"
144 | },
145 | {
146 | "size": "98x98",
147 | "idiom": "watch",
148 | "scale": "2x",
149 | "role": "quickLook",
150 | "subtype": "42mm"
151 | }
152 | ],
153 | "info": {
154 | "version": 1,
155 | "author": "xcode"
156 | }
157 | }
--------------------------------------------------------------------------------
/Samples/Droid/Sample.Droid.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | AnyCPU
6 | {A8B989BF-FB0A-40E0-9540-0700C1585C64}
7 | {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
8 | Library
9 | Sample.Droid
10 | Sample.Droid
11 | v7.1
12 | True
13 | Resources\Resource.designer.cs
14 | Resource
15 | Properties\AndroidManifest.xml
16 | Resources
17 | Assets
18 |
19 |
20 |
21 | true
22 | full
23 | false
24 | bin\Debug
25 | DEBUG;
26 | prompt
27 | 4
28 | None
29 | arm64-v8a;armeabi;armeabi-v7a;x86
30 |
31 |
32 | true
33 | pdbonly
34 | true
35 | bin\Release
36 | prompt
37 | 4
38 | true
39 | false
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 | {4FE40048-B716-42ED-9E26-C114689BAAFD}
73 | SimpleDatabase
74 |
75 |
76 |
77 |
78 |
79 |
80 |
--------------------------------------------------------------------------------
/SimpleDatabase/Model/Group.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using SQLite;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 |
6 | namespace SimpleDatabase
7 | {
8 | class SimpleDatabaseGroup : GroupInfo
9 | {
10 | [Indexed]
11 | public string ClassName {get;set;}
12 | [Indexed]
13 | public int RowCount {get;set;}
14 | public int Order {get;set;}
15 | [Ignore]
16 | public bool Loaded {get;set;}
17 | }
18 | public class GroupInfo
19 | {
20 | bool stringIsValid = false;
21 | public GroupInfo()
22 | {
23 | Filter = "";
24 | From = "";
25 | }
26 |
27 | string groupBy;
28 | [Indexed]
29 | public string GroupBy {
30 | get { return groupBy; }
31 | set
32 | {
33 | groupBy = value;
34 | stringIsValid = false;
35 | }
36 | }
37 |
38 | public Dictionary Params { get; set;}= new Dictionary();
39 | public bool OrderByDesc { get; set;}
40 | public string GroupString {get;set;}
41 | public bool GroupOrderByDesc { get; set;}
42 |
43 | string orderBy;
44 | [Indexed]
45 | public string OrderBy {
46 | get { return orderBy;}
47 | set
48 | {
49 | orderBy = value;
50 | stringIsValid = false;
51 | }
52 | }
53 |
54 | string filter;
55 | [Indexed]
56 | public string Filter
57 | {
58 | get { return filter; }
59 | set
60 | {
61 | filter = value;
62 | stringIsValid = false;
63 | }
64 | }
65 |
66 | string from;
67 | public string From {
68 | get { return from;}
69 | set {
70 | from = value;
71 | stringIsValid = false;
72 | }
73 | }
74 |
75 | public int Limit {get;set;}
76 |
77 | public GroupInfo Clone ()
78 | {
79 | return new GroupInfo
80 | {
81 | GroupBy = this.GroupBy,
82 | OrderByDesc = this.OrderByDesc,
83 | GroupString = this.GroupString,
84 | GroupOrderByDesc = this.GroupOrderByDesc,
85 | OrderBy = this.OrderBy,
86 | Filter = this.Filter,
87 | From = this.From,
88 | Limit = this.Limit,
89 | Params = Params?.ToDictionary(x => x.Key, x => x.Value) ?? new Dictionary(),
90 | };
91 | }
92 |
93 | public string FromString(string table)
94 | {
95 | return $" {table} {From} ";
96 | }
97 |
98 | public string OrderByString(bool includeOrerBy = true)
99 | {
100 |
101 | if (string.IsNullOrEmpty (OrderBy))
102 | return "";
103 | string orderby = includeOrerBy ? " order by " : " , ";
104 | orderby += (string.IsNullOrEmpty(GroupBy) ? "" : GroupBy + (GroupOrderByDesc ? " desc " : "") + " , ") + OrderBy + ( OrderByDesc ? " desc " : "");
105 | return orderby;
106 | }
107 |
108 | public string FilterString(bool includeWhere)
109 | {
110 | if (string.IsNullOrEmpty (Filter))
111 | return "";
112 | string filter = includeWhere ? " where " : " and ";
113 | filter += Filter;
114 | return filter;
115 | }
116 |
117 | public void AddFilter(string filter)
118 | {
119 | if (string.IsNullOrEmpty (Filter))
120 | Filter = filter;
121 | else
122 | Filter += " and " + filter;
123 | }
124 |
125 | public string LimitString()
126 | {
127 | return (Limit > 0 ? " Limit " + Limit : " ");
128 | }
129 |
130 | public override bool Equals (object obj)
131 | {
132 | return obj.ToString() == this.ToString();
133 | }
134 |
135 | public override int GetHashCode()
136 | {
137 | return this.ToString().GetHashCode();
138 | }
139 |
140 | public static bool operator == (GroupInfo x, GroupInfo y)
141 | {
142 | if (object.ReferenceEquals (x, y)) {
143 | // handles if both are null as well as object identity
144 | return true;
145 | }
146 |
147 | if ((object)x == null || (object)y == null) {
148 | return false;
149 | }
150 | return x.Equals (y);
151 | }
152 |
153 | public static bool operator != (GroupInfo x, GroupInfo y)
154 | {
155 | if (object.ReferenceEquals (x, y)) {
156 | // handles if both are null as well as object identity
157 | return false;
158 | }
159 |
160 | if ((object)x == null || (object)y == null) {
161 | return true;
162 | }
163 | return !x.Equals (y);
164 | }
165 |
166 | string toStringValue;
167 | public override string ToString ()
168 | {
169 | if (!stringIsValid || string.IsNullOrEmpty(toStringValue))
170 | {
171 | toStringValue = $"[GroupInfo: GroupBy={GroupBy}, OrderBy={OrderBy}, Filter={Filter}, From={From} ,Params{string.Join(",", Params)}]";
172 | stringIsValid = true;
173 | }
174 | return toStringValue;
175 | }
176 |
177 | public Tuple ConvertSqlFromNamed(string sql, Dictionary injectedParams = null)
178 | {
179 | return ConvertSqlFromNamed(sql,Params,injectedParams);
180 | }
181 |
182 | public static Tuple ConvertSqlFromNamed(string sql, Dictionary namedParameters, Dictionary injectedParams = null)
183 | {
184 | var foundParamters = sql.Split(' ','(',')').Where(x => x.StartsWith("@")).Select(x => x.Trim().TrimEnd(')')).ToList();
185 | var hasQuestion = sql.Contains("?");
186 | if (hasQuestion)
187 | {
188 | throw new Exception("Please covert to named parameters");
189 | }
190 |
191 | string returnSql = sql;
192 | List