Custom Dialog with Xamarin Android

This is a continuation of my last post where I showed how to save and retrieve an item to the Android SQLite database using SQLite.Net ORM. In this post I want to show how to use Custom Dialog with Xamarin Android to add an item to the same database. Tutorials on Android Master List details normally show either two Activities or an Activity and a Fragment. In this post, I will use the Main Activity already added in the last post and then create a Custom Dialog with Android. Below is what the completed dialog will look like and the code for this tutorial can be found in Github.
Just to re-state what I will be implementing in this tutorial, there will be a button on the Main Activity called “Add Services” that when clicked will launch a custom dialog over the Activity. A little interesting twist is that there is a drop down list for the Categories. This could have been a text field, but in real life Categories are often drop down list that are backed by a data source. In Android, drop down list are implemented with the Spinner class. So I have not only added a Spinner but I have added the ability to populate that Spinner on the fly so the user can add a Category that does not yet exist and have that Category become immediately available on the drop down list. The data source for the drop down list is yet another table in the SQLite database. Let’s start with the UI for the Custom dialog.

User Interface for a Custom Dialog with Xamarin Android

If you are following from the last tutorial with this source code, go ahead and add a layout file under layout sub-folder of the Resources folder. I have named my file AddServiceDialog.xaml and here is what the design tab will look like. You can design iwth the designer or you can just go ahead and copy and paste the XML code below.

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

29

30

31

32

33

34

35

36

37

38

39

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

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

<?xml version="1.0"encoding="utf-8"?>

<ScrollView xmlns:p1="http://schemas.android.com/apk/res/android"

p1:minWidth="25px"

p1:minHeight="25px"

p1:layout_width="match_parent"

p1:layout_height="match_parent"

p1:id="@+id/scrollView1">

<LinearLayout

p1:orientation="vertical"

p1:minWidth="25px"

p1:minHeight="25px"

p1:layout_width="match_parent"

p1:layout_height="wrap_content"

p1:id="@+id/linearLayoutContainer"

p1.gravity="center">

<TextView

p1:text="Add Service Item"

p1:textAppearance="?android:attr/textAppearanceLarge"

p1:layout_width="wrap_content"

p1:layout_height="wrap_content"

p1:layout_gravity="left"

p1:id="@+id/textTitle"/>

<TextView

p1:text="Name"

p1:textAppearance="?android:attr/textAppearanceMedium"

p1:layout_width="wrap_content"

p1:layout_height="wrap_content"

style="@style/LabelStyle"

p1:id="@+id/textViewName"/>

<View

style="@style/DividerStyle"/>

<EditText

p1:layout_width="match_parent"

p1:layout_height="wrap_content"

p1:id="@+id/editTextName"/>

<TextView

p1:text="Description"

p1:textAppearance="?android:attr/textAppearanceMedium"

p1:layout_width="wrap_content"

p1:layout_height="wrap_content"

style="@style/LabelStyle"

p1:id="@+id/textViewDescription"/>

<View

style="@style/DividerStyle"/>

<EditText

p1:layout_width="match_parent"

p1:layout_height="wrap_content"

p1:id="@+id/editTextDescription"/>

<TextView

p1:text="Price"

p1:textAppearance="?android:attr/textAppearanceMedium"

p1:layout_width="wrap_content"

p1:layout_height="wrap_content"

style="@style/LabelStyle"

p1:id="@+id/textViewPrice"/>

<View

style="@style/DividerStyle"/>

<EditText

p1:layout_width="match_parent"

p1:layout_height="wrap_content"

p1:id="@+id/editTextPrice"/>

<LinearLayout

p1:orientation="horizontal"

p1:layout_width="match_parent"

p1:layout_height="wrap_content"

p1:id="@+id/linearLayout1">

<Spinner

p1:layout_width="0dp"

p1:layout_height="match_parent"

p1:layout_weight="1"

p1:gravity="center_vertical"

p1:id="@+id/spinnerCategory"/>

<CheckBox

p1:text="Add New Category?"

p1:layout_width="wrap_content"

p1:layout_height="wrap_content"

p1:id="@+id/checkBoxAddCategory"/>

</LinearLayout>

<LinearLayout

p1:orientation="horizontal"

p1:layout_width="match_parent"

p1:layout_height="wrap_content"

p1:id="@+id/linearLayoutCategorySection">

<EditText

p1:layout_width="0dp"

p1:layout_weight="1"

p1:layout_height="wrap_content"

p1:id="@+id/editTextAddCategory"/>

<Button

p1:text="Button"

p1:layout_width="wrap_content"

p1:layout_height="wrap_content"

p1:id="@+id/buttonCategory"/>

</LinearLayout>

</LinearLayout>

</ScrollView>

What we have here is a Linear layout with two nested Linear Layout wrapped with a ScrollView. Notice the Checkbox, what that does is it hides and shows a field that is used to add a Category. For example if a user is adding a Service called Income Tax Preparation Service and the Category for this service is called “Professional Service” if this category already exist in the drop down list then the user can just select it there is no need to show the field to add category in this case but if the Category does not exist then the user can click the Checkbox which will expand the fields to show the Add Category field.

Category Table
Since we are saving the categories to the database, we need to create a Table to hold the list of categories. And since we are using the SQLite.Net to manage persistence we need to to create a class that the SQLite.net ORM will work with. So go ahead and add a class to the Model folder called ServiceCategory.cs and the this class only has a Name property for now and it inherits from the IBusinessEntity this way we can re-use the existing database logic which works with anything that extends IBusinessEntity.

1

2

3

4

5

6

publicclassServiceCategory:IBusinessEntity

{

[PrimaryKey,AutoIncrement,Column("_id")]

publicintId{get;set;}

publicstringName{get;set;}

}

And then you add a statement to create the Category table to the ServiceDatabase.cs file like so

1

CreateTable<ServiceCategory>()

We will also need to create CategoryRepository class that will handle the CRUD operation for the Categories class and also create a ServiceManager.cs that uses Repository. This may appear like unneccessary overhead but it does allow for code maintainability in the long run. I believe that it is possible to have a Generic Repository of type T so that we do not have to create a new repository class each time. I will look into that later. Look at the Github repo for the repository and manager class code.

Creating a Custom Xamarin Android Catalog
Add a file to the root of the project called ServiceDialog.cs, this is a standard C# class and we will go ahead and make it inherit from DialogFragment. In this class we will do the following:

Create a method that instantiates and returns a new instance of this dialog

Inflate the view for this dialog which is the layout we created above

Create and initialize the properties for this Dialog

Add event handler for the drop down list (Spinner)

Add event handler for the Save button

Add listener that tells the calling Activity that an item has been added through the dialog

Notice how we are not showing the dialog after creating it but returning it to the calling Activity. Now from the calling Activity, the MainActivity.cs in this case we just need to add a standard menu item to the Menu with text set to show always like so:

1

2

3

4

5

6

7

<?xml version="1.0"encoding="utf-8"?>

<menu xmlns:android="http://schemas.android.com/apk/res/android">

<item android:id="@+id/action_add_services"

android:title="Add Services"

android:showAsAction="always"/>

</menu>

With this we can now instantiate the custom dialog when someone clicks on the “Add Services” button in the menu overflow like so:

1

2

3

4

5

6

7

8

9

10

11

12

13

publicoverride boolOnOptionsItemSelected(IMenuItem item)

{

varid=item.ItemId;

//If someone clicks on the Add Service button

if(id==Resource.Id.action_add_services)

{

//Create a new dialog and all show on

//That dialog

vardialog=ServiceDialog.NewInstance();

dialog.Show(FragmentManager,"dialog");

}

returnbase.OnOptionsItemSelected(item);

}

And that is it, with this you are now able to add an item to the Custom list and you will be able to add categories dynamically. And with a little massaging you should be able to re-use the same dialog to edit the item. Because of the way that the custom listview was created, the new items will show up immediately after you add them because after you dismiss the custom dialog box and return back to the MainActivity, the onResume method is called and in there is a method called LoadData() which reloads the data for the custom listview including the item that you just added so the listview is up to date. That is it with adding custom dialog with Xamarin Android. Happy coding