Sunday, November 24, 2013

Android: App for Monitoring Expenses

In this post I want to introduce a a bit more advanced project, in which all tips from the previous posts are used.
The project stems from my own needs and the resulting app is also used by me a lot - it is an app in which expenses can be recorded and monitored easily.
The app consists out of 4 activities: MainActivity.cs and Overview[A - C].cs, as well as 2 helper classes, Tools.cs and Expenses.cs.
Expenses.cs describes the class Expenses, which is used for representing expenses.
Conducted expenses are serialized and added to the expense file of the current month.
The main activity looks as follows:

With a click on "Overview" we change to the activity OverviewA. For this the expenses list is serialized to a string and given as a parameter to OverviewA.
In OverviewA all expenses are listed by date for each month, which can be selected on top.
If the list gets too long, of course one can scroll down.




















In OverviewB expenses are grouped to categories (by name):



Finally in OverviewC the share of the categories is displayed graphically using a pie chart:
















The complete source code of the app can be downloaded here.

More to see how it works I also uploaded a (improved version) to the Google Play store.

Android: Add Scrollbars

Suppose, we want to create the following layout:

using System;
using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;

namespace ScrollbarsExample
{
     [Activity (Label = "ScrollbarsExample", MainLauncher = true)]
     public class MainActivity : Activity
     {
          protected override void OnCreate (Bundle bundle)
          {
               base.OnCreate (bundle);

               var Layout = new LinearLayout (this);
               Layout.Orientation = Orientation.Vertical;

               for (int i=0; i<20; i++) {
                    var TempButton = new Button (this);
                    TempButton.Text = "Button" + i.ToString ();
                    Layout.AddView (TempButton);
               }

               SetContentView (Layout);
          }
     }
}

So a layout, in which 20 buttons are placed vertically next to each other. Probably this will not fit completely on the cellphone screen, the app is then simply "cut off".
But we can very easily add a scrollfunction to the app, that means a possibility for the user to scroll up or down and thus can see the whole layout.
For that we add as the outmost container a ScrollView. Then we add the layout via AddView() to the ScrollView, and eventually we set the layout of the application to the ScrollView:


using System;
using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;

namespace ScrollbarsExample
{
     [Activity (Label = "ScrollbarsExample", MainLauncher = true)]
     public class MainActivity : Activity
     {
          protected override void OnCreate (Bundle bundle)
          {
               base.OnCreate (bundle);

               var MyScrollView = new ScrollView (this);

               var Layout = new LinearLayout (this);
               Layout.Orientation = Orientation.Vertical;

               for (int i=0; i < 20; i++) {
                    var TempButton = new Button (this);
                    TempButton.Text = "Button" + i.ToString ();
                    Layout.AddView (TempButton);
               }

               MyScrollView.AddView (Layout);
               SetContentView (MyScrollView);
          }
     }
}

Now the user can scroll via finger movement vertically through the application.
If the layout is horizontally wider than the screen, we achieve a horizontal scrolling possibilty by using the control HorizontalScrollView.

Saturday, November 23, 2013

Android: Close Current Activity

In this post I just want to show quickly, how the current activity can be terminated.
This is for example helpful, when starting a new activity and not wanting to have the original activiy open in the background.
The code is:

this.Finish ();

Friday, November 22, 2013

Android: Switch Between Activities

After I mentioned a couple times in the previous posts, that Android applications are made up out of activities (just like Windows Forms applications are of forms), I want to show today, how a new activity can be added to the application, how this can be started and how data can be transfered.
We add a new activity via File - New - Android Activity, I call it here "SecondActivity.cs".
Of course we can now work with it analogously like with the main activity.
So we can create a layout via code, or via an axml file. I here choose the second option, for that we right click on Resources - layout and select Add - New File - Android Layout. I name the layout "Second".
From the main activity we then can start the second activity as follows:

var SecondActivity = new Intent(this, typeof(SecondActivity));
StartActivity(SecondActivity);

Optionally we can pass over string parameters when starting:

SecondActivity.PutExtra("Parameter", "Nachricht von Main");

The complete code of the file "MainActivity.cs" looks like this:

using System;
using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;

namespace MultipleActivities
{
     [Activity (Label = "MultipleActivities", MainLauncher = true)]
     public class MainActivity : Activity
     {
          protected override void OnCreate (Bundle bundle)
          {
               base.OnCreate (bundle);

               var Layout = new LinearLayout (this);
               Layout.Orientation = Orientation.Vertical;
               var Button1 = new Button (this);
               Button1.Text = "Second starten";

               Button1.Click += delegate {
                    var SecondActivity = new Intent(this, typeof(SecondActivity));
                    SecondActivity.PutExtra("Parameter", "Nachricht von Main");
                    StartActivity(SecondActivity);
               };

               Layout.AddView (Button1);

               SetContentView (Layout);
          }
     }
}

So when clicking the button, the second activity is started.
This only contains a textview, the corresponding layout code of the file "Second.axml" is:

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:minWidth="25px"
    android:minHeight="25px">
    <TextView
        android:text="Medium Text"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:id="@+id/textView1" />
</LinearLayout>

The code of the activity "SecondActivity.cs" is also pretty short, in it just the parameter passed over by the main application is read-out and displayed in the textview:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;

namespace MultipleActivities
{
     [Activity (Label = "SecondActivity")]              
     public class SecondActivity : Activity
     {
          protected override void OnCreate (Bundle bundle)
          {
               base.OnCreate (bundle);
               SetContentView (Resource.Layout.Second);

               TextView textView1 = FindViewById (Resource.Id.textView1);
               textView1.Text = Intent.GetStringExtra ("Parameter");
          }
     }
}

Thursday, November 21, 2013

Android: Change App Title

In today's short post I want to explain how to change the title of an Android app, more specifically speaking, the title of the single app windows (activities).
When creating a new app, the main activity looks as follows, the title (circled in red) is the name of the project:








To change this, we simply replace it in the following line, which is located as an attribute directly above the definition of the activity class:

[Activity (Label = "New Title", MainLauncher = true)]

Via code we can change the title over the property Title:

this.Title = "Algo";

Tuesday, November 19, 2013

Android: Add Graphics to Layout

In the previous post I recommended to derive a class from View for creating graphics, do the drawing in this class and then set this class as layout.
This now seemingly causes problems when creating more advanced applications, when one also wants to place controls etc. on the application, since the command SetContentView() can only be called once. So either with the layout containing the controls, or with the custom class which draws the graphics.
But this "problem" can be solved pretty easily, by adding the graphic class like a control to the layout Layout containing the controls, and then setting the application layout to Layout.
I think, the following example code should be self explaining after reading the previous posts.
We here create the class ViewWithOval, which is nearly identical to the class from the previous post. It draws a circle on the form, the only difference is the public variable paint for setting the color of the circle.
In the function OnCreate() of the class MainActivity we then create a layout with a button. After clicking the button, we change the color of the circle and enforce the redrawing via Invalidate(). Then we add the circle to the layout and set the layout of the application:

using System;
using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;

namespace CombinedLayouts
{
     [Activity (Label = "CombinedLayouts", MainLauncher = true)]
     public class MainActivity : Activity
     {

          protected override void OnCreate (Bundle bundle)
          {
               base.OnCreate (bundle);

               var Layout = new LinearLayout (this);
               Layout.Orientation = Orientation.Vertical;

               var Button1 = new Button(this);
               Layout.AddView (Button1);

               ViewWithOval OvalGraphic = new ViewWithOval (this);
              
               Button1.Click += delegate {
                    OvalGraphic.paint.SetARGB(255, 255, 0, 0);
                    OvalGraphic.Invalidate();
               };

               Layout.AddView (OvalGraphic);

               SetContentView (Layout);
          }
     }

     public class ViewWithOval : View
     {
          public Android.Graphics.Paint paint = new Android.Graphics.Paint ();
          private readonly Android.Graphics.Drawables.ShapeDrawable Oval;

          public ViewWithOval(Context context) : base (context)
          {       
               paint.SetARGB(255, 0, 255, 0);

               Oval = new Android.Graphics.Drawables.ShapeDrawable(new Android.Graphics.Drawables.Shapes.OvalShape());
               Oval.Paint.Set(paint);

               Oval.SetBounds(0, 0, 500, 500);
          }

          protected override void OnDraw(Android.Graphics.Canvas canvas)
          {
               Oval.Paint.Set(paint);
               Oval.Draw(canvas);
          }
     }
}


Android: Graphics

In the Android app programming there are essentially two possibilites to create 2D graphcics: On the one hand this can be done with so called DrawableResources or by using a Canvas object.
DrawableResources are geometrical figures, which are defined in a XML file and then shown on the app.
In contrast to that on a Canvas object can be arbitrarily drawn, similiar to the functions of System.Graphics.

First a short example about DrawableResources: We right click on the folder Resources - Drawable and select Add File - XML file. Into this we insert the following code:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="line">
    <stroke android:width="1dp" android:color="#FFFFFF"/>
    <size android:height="50dp" />
</shape>

So first we define, that the file describes a figure (shape), and determine, that we want to represent a line.
This should be 1dp wide and 50dp long, furtheremore have black color. Dp stands for Density-independent Pixels and is a measure unit, which adapts to the physical screen size. The defined figure then can for example be used as a background for a control (my file is called Line.xml):

var TxtLine = new TextView (this);
TxtLine.SetBackgroundResource(Resource.Drawable.Line);

Of course other figures besides line are avaible, on this page of Xamarin there is another example.

Now I want to spend a bit more time on the second described method. A commonly used technique is the creation of a custom View class, in which the drawing is done, and which is then set as a layout for the application.
I will here draw an ellipse, based upon this tutorial by Xamarin.
I simply post the complete code of the class first:

     public class ViewWithOval : View
     {
          private readonly ShapeDrawable Oval;

          public ViewWithOval(Context context) : base (context)
          {
               var paint = new Paint();
               paint.SetARGB(255, 0, 255, 0);

               Oval = new ShapeDrawable(new OvalShape());
               Oval.Paint.Set(paint);

               Oval.SetBounds(0, 0, 500, 500);
          }

          protected override void OnDraw(Canvas canvas)
          {
               Oval.Draw(canvas);
          }
     }

So we create a class named ViewWithOval, and let it inherit from the base class View. In it we save a variable of the type ShapeDrawable, in which we can save an arbitrary drawing figure. In the constructor of the class we determine, that we want to have an oval. Furthermore we set its color to green. Via SetBounds() we set the drawing area, which will be fully used by the oval. So the quadratical area here leads to the drawing of a circle.
Important is the overloading of the function OnDraw(), which is called when the class is redrawn, here we take care of the drawing of the shape.
In this we could for example also draw other objects, e.g. via canvas.DrawText("I draw a string", ...), a string.
In our MainActivity we now only have to set the layout to this new class, which we do in the OnCreate() function with the following command:

SetContentView (new ViewWithOval(this));

The result looks as follows on my cellphone:


Sunday, November 17, 2013

Android: Layouting

Today I want to analyze the topic layouting for Android apps a bit more in depth and especially show the usage of the TableLayout, with which already a lot can be done.
In the two previous posts we created a first Android application and in that placed controls with a LinearLayout below each other.
With a TableLayout controls can, as the name already tells, be arranged in a table form, so that virtually arbitrary positions are possible.
First I will describe the creation of the layout via an AXML file, like described in the previous post, and eventually show the C# code, which gives us the same result.
In the file "Main.axml" we first change the layout from Linear to Table:

<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">

A TableLayout consists of TableRows (rows). In each row we can place controls, which then are arranged next to each other.
We can add a new line to the layout and to that a new textview control as follows:

<TableRow>
    <TextView
        android:text="Textview1"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/textView1" />
</TableRow>

By inserting an empty TableRow we can add a vertical space. Beneath it, we add a new line with a button and a textview:

<TableRow>
</TableRow>
<TableRow>
    <Button
        android:id="@+id/button1"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="Button1" />
    <TextView
        android:text="Textview2"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/textView2" />
</TableRow>

The resulting layout looks as follows:










The single table cells adapt in their horizontal alignment and size, meaning for example, the cell, which contains Button1, has the same size as the cell of Textview1. If this increases because for example the text gets longer, also the cell of Button1 gets wider, Textview2 moves to the right.
If you want to add a control independent of this mechanism, for example a headline which does not influence the size of the following cells, you declare it without a containing TableRow.
Here the complete axml code with another textview, which contains a long headline on the top part of the screen:

<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <TextView
        android:text="Looooong Headline"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/textView3" />
    <TableRow>
        <TextView
            android:text="Textview1"
            android:textAppearance="?android:attr/textAppearanceMedium"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/textView1" />
    </TableRow>
    <TableRow>
    </TableRow>
    <TableRow>
        <Button
            android:id="@+id/button1"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="Button1" />
        <TextView
            android:text="Textview2"
            android:textAppearance="?android:attr/textAppearanceMedium"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/textView2" />
    </TableRow>
</TableLayout>

Now as promised the content of the file "MainActivity.cs", which alternatively to the possibilty of using axml code, as describe above, generates the same result:

using System;
using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;

namespace TableLayoutExample
{
     [Activity (Label = "TableLayout", MainLauncher = true)]
     public class MainActivity : Activity
     {
          protected override void OnCreate (Bundle bundle)
          {
               base.OnCreate (bundle);

               var Layout = new TableLayout (this);
               Layout.Orientation = Orientation.Vertical;

               var Textview3 = new TextView (this);
               Textview3.Text = "Looooong Headline";
               Layout.AddView (Textview3);

               TableRow TableRow1 = new TableRow (this);
               var Textview1 = new TextView (this);
               Textview1.Text = "Textview1";
               TableRow1.AddView (Textview1);
               Layout.AddView (TableRow1);

               TableRow TableRow2 = new TableRow (this);
               Layout.AddView (TableRow2);

               TableRow TableRow3 = new TableRow (this);
               var Button1 = new Button (this);
               Button1.Text = "Button1";
               var Textview2 = new TextView (this);
               Textview2.Text = "Textview2";
               TableRow3.AddView (Button1);
               TableRow3.AddView (Textview2);
               Layout.AddView (TableRow3);

               SetContentView (Layout);
          }
     }
}


Android: Define App Layout via AXML

In the previous post I explained the creation of a first Android app. There we added 2 controls to the app window, a textview and a button, and aligned them vertically with a LinearLayout. The creation of the controls and their alignment we did in the code of the OnCreate() function.
But also like in WPF applications, in Android apps the layout can be defined via a file which is based upon an XML format. In today's post I want to write about that and create the layout of the app from the previous post with this principle.
Xamarin saves the layout as an axml file. When creating a new project, for the mainactivity a corresponding layout file is created. This can be found when expanding the folder "Resources" on the left side, then "layout" under the name "main.axml".
If you click on it, it opens, now either like in Visual Studio controls can be added to the window via drag & drop or after clicking "source" via AXML code. I will here describe the second alternative.
The first lines of the file look like this:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">

Here amongst others the XML version to be used is set, and, for us important, the type of layout is determined, which is already the desired LinearLayout.
We now add with some lines of XML code, which should be self explanatory, the controls:

<TextView
android:text="Hello Android"
    android:textAppearance="?android:attr/textAppearanceMedium"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/TextView1" />
<Button
    android:id="@+id/Button1"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="Click me" />

After a click on "Content", a preview of the program window is shown:
The complete XML code of the file is:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <TextView
     android:text="Hello Android"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/TextView1" />
    <Button
        android:id="@+id/Button1"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="Click me" />
</LinearLayout>

Back in the C# code of the file "MainActivity.cs" we have to tell the program, that it should use the layout from the resources, which we do with
SetContentView (Resource.Layout.Main);

Via Resource.Layout we access the resource folder, Main(.axml) is the name of our desired file.
To be able to access the controls, we have to reference them via their ID:

Button Button1 = FindViewById<button> (Resource.Id.Button1);
TextView TextView1 = FindViewById (Resource.Id.TextView1);

The remaining code for adding an event handler is of course the same, the complete code of the file "MainActivtiy.cs" is:

using System;
using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;

namespace FirstApplicationAXML
{
     [Activity (Label = "FirstApplicationAXML", MainLauncher = true)]
     public class MainActivity : Activity
     {
          protected override void OnCreate (Bundle bundle)
          {
               base.OnCreate (bundle);

               SetContentView (Resource.Layout.Main);

               Button Button1 = FindViewById<button> (Resource.Id.Button1);
               TextView TextView1 = FindViewById (Resource.Id.TextView1);

               Button1.Click += delegate {
                    TextView1.Text = "Button clicked";
               };
          }
     }
}

Saturday, November 16, 2013

Android: Creating a First App

Today's post is about the creation of a first Android app using Xamarin.
For that we open the Xamarin studio and select File - New Project - C# - Android Application.
What are forms for example in Windows Forms applications, activities are in Android, which represent a window of the application. Therefore, for us the file "MainActivity.cs" is important, since it contains the code of the main window (and so far only one) of the application.
We see, that the activity is represented as a class (MainActivity) like in Windows Forms applications . After the creation of the project this already contains the funtion OnCreate(). This is called, when the app is started. For demonstration purposes the function is already filled with code, which we delete, except the first line (base.OnCreate (bundle);).
We now want to create a simple application consisting of a textfield and a button.
Therefor we first have to create a layout to determine, how the controls should be arranged on the window. We here use a LinearLayout, in which controls are simply placed vertically or horizontally next to each other:

var Layout = new LinearLayout (this);
Layout.Orientation = Orientation.Vertical;

Layouts and controls expect in their constructor a so called context, here we pass over this for the current acticity.
Now we create the controls via code, a Label is here called Textview:

var TextView1 = new TextView (this);
TextView1.Text = "Hello Android";
Layout.AddView (TextView1);

As you can see, in the last line we add the control to the layout.
Adding the button is done analogously, just that we use an anonymous method to create an event handler for the Click event:

var Button1 = new Button (this);
Button1.Text = "Click me";
Button1.Click += delegate {
     TextView1.Text = "Button clicked";
};
Layout.AddView (Button1);

Eventually, we have to tell the activity which layout to use:

SetContentView (Layout);

With that, the app is ready for running. The complete code:

using System;
using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;

namespace FirstApplication
{
     [Activity (Label = "FirstApplication", MainLauncher = true)]
     public class MainActivity : Activity
     {
          protected override void OnCreate (Bundle bundle)
          {
               base.OnCreate (bundle);

               var Layout = new LinearLayout (this);
               Layout.Orientation = Orientation.Vertical;

               var TextView1 = new TextView (this);
               TextView1.Text = "Hello Android";
               Layout.AddView (TextView1);

               var Button1 = new Button (this);
               Button1.Text = "Click me";
               Button1.Click += delegate {
                    TextView1.Text = "Button clicked";
               };
               Layout.AddView (Button1);

               SetContentView (Layout);
          }
     }
}

The app then can be started via Execute - Start (without) Debugger. For that either a connected cellphone or an emulator has to be chosen. I did not configure any emulators, but always test on my phone. Xamarin loads the app to the phone, where it is automatically executed.
To copy the app manually to a phone, it has to be compiled as a release version (Project - Active Configuration - Release), then the file "AppName.AppName-Signed.apk" from the release folder can be copied to the desired target directory. Android only allows signed apps to run, which is already done by Xamarin in the "Signed" file. If the app is to be published in a wider field (for example on Google Play), it should (must) be personally signed though.

Thursday, November 14, 2013

Install Xamarin

In this post I briefly want to describe the installation and setting up of the Xamarin studio, which is needed for the app programming for Android and iOS.
Xamarin can be downloaded under this link. For installation, simply follow the instructions.
Like I already mentioned in the previous post, I limit my posts on this blog to Android programming.
Here you find a guide of Xamarin regarding the installation, as well as advices for configuring the development environment. I though had to follow only 2 of the steps, which were the installation of the USB drivers and the setting of the cellphone in the debug mode.
There are special drivers needed, so that one can transfer the application (for debug purposes) on the phone.
Both steps are described on the linked page, there you also find a list of matching drivers for different manufactures. For my Samsung S3 the installation of the maintenance program "Kies" was sufficient (I do not know, if it had even worked without installing it).
And already your computer and cellphone are ready for app development!
A little drawback: Allegedly Xamarin should automatically integrate in the .Net development environment, which did not happen in my case. But I get along well with the Xamarin studio, it probably is even better for app development.

App Programming with C#

Probably most of you will know Java as development language for Android and Apple's studio for iOS - but app development can also be done with C#!
Therefore I want to show you in this next series of posts, how to develop Android and iOS apps using C#.
Core for this is the Xamarin Studio, which is based on Mono. Mono is a plattform independent implementation of the .Net Framework, amongst others for Linux, and now for Android and iOS too.
With the help of Xamarin apps can be written in standard C# code, meaning of course the known C# syntax is used, furthermore all functions and libraries not bound to Windows can be used, such as streams, serialization, file access etc.
The compiler then translates the code in the right format for Android or iOS.
Due to the fact I only have an Android phone, (for now) on this blog I unfortunately have to limit myself to Android programming.
I will label some posts with the prefix "Android:" in the title, to avoid every mix-up despite labels with posts regarding common Windows programming.
One drawback comes with Xamarin though - the free version allows only apps up to a certain file size and furthermore prohibts the use of external Java library, which would be necessary for displaying ads.

Monday, November 11, 2013

WPF Tutorial Part 4 - Databinding

Another nice feature of WPF is Databinding. With that we mean the possibility of connecting the graphical user interface directly with the underlying data - for example a textbox with a string variable of a class. Depending on the settings then a change in the string is directly shown in the textbox and / or the otherway around.

In today's post I want to present an example for this, which manages data of an employee. An employee is represented by the class Employee, saved are first name, last name, salary and position.
In databinding always one form, control or the like is connected to an instance of a class. Here we connect the whole form with an instance of the class Employee, then the different controls on it can represent the different properties of the class.
After creating an instance with the name Employee1 we set the datasource of the form as follows (for examle in the constructor):

this.DataContext = Employee1;

The linking of the single controls to variables of the employee we do in the XAML file, for example like this:

<TextBox Name="txtName" Grid.Row="0" Grid.Column="0" Height="25" Text="{Binding Path=LastName, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"></TextBox>

As you can see, the property Text of the control is not directly a text assigned but a binding is created. Path describes the path of the binding. Since we set Employee1 as data source for the whole form, the textbox is here linked to the variable LastName of Employee1.
The property Mode describes, how changes are forwarded. TwoWay means, that changes in the textbox are to be forwarded to the connected variable and changes in this to the textbox. Further possibilites are OneWay (changes in the variable are propagated to the textbox) and OneWayToSource (changes in the textbox are forwarded to the variable).
The property UpdateSourceTrigger describes, when the binding becomes active. In the case of Explicit changes are only propagated, when the function UpdateSource() is called. LostFocus says, that changes are only accepted when the connected control loses focus, and the here used PropertyChanged describes, that changes are to be forwarded immediately.

Requirement for using databinding is the use of a getter and setter.
For the variable LastName this can look for example as follows:

private string lastName;
public string LastName
{
    get { return lastName; }
    set
    {
        lastName = value;
    }
}

The "actual" variable is here lastName. But this is "hidden" behind the public field LastName, which can return the value via get or set it via set.
The advantage of this is the possibility of checking and maintaining data consistency.

If you run the code like this, you will find a problem: Changes in the textbox are forwarded to the variable, meaning it saves the new value, but changes in the variable are not displayed in the textbox. We have to trigger this manually. For that first the class Employee has to inherit from INotifyPropertyChanged. Subsequently, we create a notify function:

        public event PropertyChangedEventHandler PropertyChanged;

        private void Notify(string argument)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(argument));
            }
        }

In the setter of the variable we then call this function, so e.g. Notify("LastName").
Now the databinding works in both directions.

One last thing I want to mention is DataConversion. In the code there is a property Salary of type int and Position of the type of a custom enumeration. In the databinding these are automatically converted to a string, which is no problem, since .Net knows conversions for this. But what, if you have written a custom class and want to convert this to a string for representation in a textbox? Then you have to write a converter. But of course you can also use one like that, e.g. for customizing the conversion.
I do this here for the conversion of the enumeration. It contains 3 values: Undefined, Trainee and Manager. Although Employee1 was not assigned anything, the textbox responsible for Position displays Undefined (the same holds for salary: 0). We now change this, so that "" is returned in the conversion when the variable is set to Undefined.
For that we need a converter class, which we write ourselves:

    [ValueConversion(typeof(Employee.Positions), typeof(string))]
    public class EmployeePositionsConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if ((int)value == 0)
                return "";
            else
                return value.ToString();
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            switch ((string)value)
            {
                case "Trainee":
                    return Employee.Positions.Trainee;
                case "Manager":
                    return Employee.Positions.Trainee;
                default:
                    return Employee.Positions.Undefined;
            }
        }
    }

Above the name we declare, between which 2 types we convert. The function Convert() is then responsible for converting from Employee.Positions to String, ConvertBack() for the other way. I think the principle should be clear.
We now have to tell the program to use this converter. For that we first create in the XAML file in the Window tag an attribute named "c" for example, which saves our namespace:

xmlns:c="clr-namespace:WPFDatabinding"

Then we add a new ressource to the project:

    <Window.Resources>

        <c:EmployeePositionsConverter x:Key="EmployeePositionsConverter"/>
    </Window.Resources>


The meaning of this code is the following: Since in "c" our namespace is saved, we access the converter using c:EmployeePositionsConverter and make it accesible under the name EmployeePositionsConverter. In the definition of the textbox we then can simply use it:

<TextBox Name="txtPosition" Grid.Row="3" Grid.Column="0" Height="25" Text="{Binding Path=Position, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay, Converter={StaticResource EmployeePositionsConverter}}"></TextBox>

Now the complete code of the program - there are 4 textboxes and 2 buttons contained. The textboxes represent the properties of Employee1 as described. After clicking Button 1 Employee1 is filled with data (he then is "Hans Wurst"), the textboxes change accordingly. We can also enter data in the textboxes, when clicking Button 2 the data saved in Employee1 are displayed.

MainWindow.xaml:


<Window x:Class="WPFDatabinding.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:c="clr-namespace:WPFDatabinding"

        Title="MainWindow" Height="350" Width="525"
        >

    <Window.Resources>
        <c:EmployeePositionsConverter x:Key="EmployeePositionsConverter"/>
    </Window.Resources>

    <Grid Height="160" Width="200" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="15">
        <Grid.RowDefinitions>
            <RowDefinition Height="30"/>
            <RowDefinition Height="30"/>
            <RowDefinition Height="30"/>
            <RowDefinition Height="30"/>
            <RowDefinition Height="30"/>
        </Grid.RowDefinitions>
        <TextBox Name="txtName" Grid.Row="0" Grid.Column="0" Height="25" Text="{Binding Path=LastName, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"></TextBox>
        <TextBox Name="txtFirstName" Grid.Row="1" Grid.Column="0" Height="25" Text="{Binding Path=FirstName, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"></TextBox>
        <TextBox Name="txtSalary" Grid.Row="2" Grid.Column="0" Height="25" Text="{Binding Path=Salary, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"></TextBox>
        <TextBox Name="txtPosition" Grid.Row="3" Grid.Column="0" Height="25" Text="{Binding Path=Position, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay, Converter={StaticResource EmployeePositionsConverter}}"></TextBox>
        <Button Name="btnNew" Grid.Row="4" Grid.Column="0" Width="100" Height="25" Click="btnNew_Click" Margin="-80, 0, 0,0">Hans Wurst</Button>
        <Button Name="btnCheck" Grid.Row="4" Grid.Column="0" Width="50" Height="25" Click="btnCheck_Click"  Margin="80, 0, 0,0">Check</Button>
    </Grid>
</Window>

MainWindow.xaml.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

using System.ComponentModel;

namespace WPFDatabinding
{
   ///







   /// Interaktionslogik für MainWindow.xaml
   ///

    public partial class MainWindow : Window
    {
        Employee Employee1 = new Employee();
        public MainWindow()
        {
            InitializeComponent();

            this.DataContext = Employee1;
        }

        private void btnNew_Click(object sender, RoutedEventArgs e)
        {
            Employee1.LastName = "Wurst";
            Employee1.FirstName = "Hans";
            Employee1.Salary = 1000;
            Employee1.Position = Employee.Positions.Trainee;
        }

        private void btnCheck_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show(Employee1.LastName + Environment.NewLine + Employee1.FirstName + Environment.NewLine + Employee1.Salary.ToString() + Environment.NewLine + Employee1.Position.ToString());
        }
    }

    [ValueConversion(typeof(Employee.Positions), typeof(string))]
    public class EmployeePositionsConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if ((int)value == 0)
                return "";
            else
                return value.ToString();
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            switch ((string)value)
            {
                case "Trainee":
                    return Employee.Positions.Trainee;
                case "Manager":
                    return Employee.Positions.Trainee;
                default:
                    return Employee.Positions.Undefined;
            }
        }
    }

    class Employee : INotifyPropertyChanged
    {
        public enum Positions {Undefined, Manager, Trainee}
        public event PropertyChangedEventHandler PropertyChanged;

        private void Notify(string argument)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(argument));
            }
        }

        private string firstName;
        private string lastName;
        private int salary;
        private Positions position;

        public string FirstName
        {
            get { return firstName; }
            set
            {
                firstName = value;
                Notify("FirstName");
            }
        }

        public string LastName
        {
            get { return lastName; }
            set
            {
                lastName = value;
                Notify("LastName");
            }
        }

        public int Salary
        {
            get { return salary; }
            set
            {
                salary = value;
                Notify("Salary");
            }
        }

        public Positions Position
        {
            get { return position; }
            set
            {
                position = value;
                Notify("Position");
            }
        }
    }
}


On Udo's Blog there is also a post regarding this topic.