Inventory Example
This article explains how to create a simple application with
the EntityLIB and TableGridLIB libraries using MonoDevelop. The picture
shows the completed application:

Creating the Project
On a Linux system, make sure it's configured with mono 1.1.18
(or later) and MonoDevelop 0.11 (or later). Invoke MonoDevelop, and click
"New Project." Then click "GTK# 2.0 Project" within the C#
item list, and enter Inventory as the project. Right click on the "References"
item in the Solution view pane, and add the "System.Data" assembly from
the .Net tab, then add the four Mark libraries that you downloaded from
Sourceforge. The project's references should look like the picture below.
Click on the Run menu item to compile and run the application. This should give
you a blank window.

Main.cs
The MainClass code should look like
the application in the picture above. Basically, you are adding the delegates
for the custom handler(s). For Linux MonoDevelop ("MD") add this
line:
public delegate void MessageHandler( string Message );
If the IDE is Visual Studio ("VS") then you need to add
these four lines:
public delegate void MessageHandler( string Message );
public delegate void UpdateHandler( string Table, string Fields, string
Where );
public delegate void InsertHandler( string Table, string Fields, string
Values );
public delegate void DeleteHandler( string Table, string Where );
The handlers are used to define the parameters of the
methods for the custom events.
MainWindows.cs
Its convenient to add code in steps to verify that each part
of it compiles.
So, the code items below cover the various parts of the file ordered by
importance. No worries, I included the whole file in a separate table at
the bottom of the screen.
The MainWindow.cs file contains the code needed for the menus and program flow.
Mono contains a built-in dialog method called MessageDialog. We'll
use this to prompt the user before quiting the application. You can quit
the application either by closing the main window (which invokes the
OnDeleteEvent) or by a button such as a menu item or toolbar button.
Double-click on the MainWindow.cs item in the Solution view,
and add the following code at the end of the class:
bool AskDialog( string Message ) {
bool response = false;
MessageDialog md = new MessageDialog (
null,
DialogFlags.DestroyWithParent,
MessageType.Question,
ButtonsType.YesNo,
Message );
int nRc = md.Run ();
if (nRc == (int)ResponseType.Yes) {
response = true;
md.Destroy();
} else {
response = false;
md.Destroy();
}
return response;
} //AskDialog
The OnDeleteEvent method should be modified as follows:
protected void OnDeleteEvent (object sender,
DeleteEventArgs a)
{
bool response = false;
response = AskDialog( "Do you really want to quit? " );
if ( response ) {
Application.Quit();
}
a.RetVal = true;
}
I like to use a common routine for messages to the statusbar
in case I want to add other features later (like a logger).
void ShowMsg( string Message ) { statusbar1.Pop( 0 ); statusbar1.Push( 0, Message ); }
At the very top of the file, make sure to declare all of the
assemblies being used in the file:
using System;
using Gtk;
using Gdk;
using System.Data;
using System.Data.Odbc;
using EntityLIB;
using TableGridLIB;
The beginning of the class should be coded as follows:
protected Gtk.VBox vbox1;
protected Gtk.MenuBar menubar1;
protected Gtk.Toolbar toolbar1;
protected Gtk.ToolButton toolbutton1;
protected Gtk.VBox vbox2;
protected Gtk.Statusbar statusbar1;
public MainWindow (): base ("")
{
this.Resizable = false;
setup();
ShowMsg( "Welcome to Inventory" );
}
void setup() {
this.DeleteEvent += new DeleteEventHandler (OnDeleteEvent);
vbox1 = new VBox();
menubar1 = new MenuBar();
toolbar1 = new Gtk.Toolbar();
vbox2 = new VBox();
statusbar1 = new Gtk.Statusbar();
//
this.Add( vbox1 );
vbox1.PackStart( menubar1, false, false, 0);
vbox1.PackStart( toolbar1, false, false, 0 );
vbox1.PackStart( vbox2, false, false, 0 );
vbox2.HeightRequest = 400;
vbox2.WidthRequest = 600;
vbox1.PackEnd( statusbar1, false, false, 0 );
this.ShowAll();
}
This code should compile and give you a basic application that
prompts you to confirm when you try to close the application. The setup()
method is declaring the basic structure of the application. The MainWindow
has added to it the "vbox1" widget. This is then packed with four items:
(1) menubar1, (2) toolbar1, (3) vbox2, and (4) statusbar1. Notice that the
vbox2 object is sized to a 400x600 rectangle; this area will be used by the rest
of the form objects in a few minutes.
More Setup Code
After you verify that the above code works properly, then
modify the setup code as follows below. This last bit of code could have
easily been configured with the MonoDevelop window designer. However, this
way you can see what's really happening and its easier to change the structure
of the application. Besides its also easier to port this code to Windows. Recompile and make sure that this
code works. Notice that each of the menu items is described (but commented
out for now).
void setup() {
AccelGroup m_AccelGroup = new AccelGroup();
this.Title = "Inventory";
this.DeleteEvent += new DeleteEventHandler (OnDeleteEvent);
this.AddAccelGroup(m_AccelGroup);
vbox2 = new VBox();
vbox1 = new VBox();
toolbar1 = new Gtk.Toolbar();
ToolButton toolbutton1 = new Gtk.ToolButton( "gtk-quit" );
toolbutton1.Label = "Quit";
//toolbutton1.Clicked += new EventHandler( OnToolbutton1Clicked );
toolbar1.Add( toolbutton1 );
ToolButton toolbutton2 = new Gtk.ToolButton( "gtk-dnd-multiple" );
toolbutton2.Label = "Product";
//toolbutton2.Clicked += new EventHandler( OnProductClicked );
toolbar1.Add( toolbutton2 );
ToolButton toolbutton3 = new Gtk.ToolButton( "gtk-indent" );
toolbutton3.Label = "Location";
//toolbutton3.Clicked += new EventHandler( OnLocationClicked );
toolbar1.Add( toolbutton3 );
ToolButton toolbutton4 = new Gtk.ToolButton( "gtk-undelete" );
toolbutton4.Label = "Container";
//toolbutton4.Clicked += new EventHandler( OnContainerClicked );
toolbar1.Add( toolbutton4 );
statusbar1 = new Gtk.Statusbar();
//
menubar1 = new MenuBar();
Menu FileMenu = new Menu();
MenuItem FileMenuItem = new MenuItem("_File");
FileMenuItem.Submenu = FileMenu;
MenuItem FileQuitMenuItem = new MenuItem("Quit");
//FileQuitMenuItem.Activated += new EventHandler(OnToolbutton1Clicked);
FileMenu.Append(FileQuitMenuItem);
Menu SetupMenu = new Menu();
MenuItem SetupMenuItem = new MenuItem("Setup");
SetupMenuItem.Submenu = SetupMenu;
MenuItem SetupProdMenuItem = new MenuItem("Product");
//SetupProdMenuItem.Activated += new EventHandler(OnProductClicked);
SetupMenu.Append( SetupProdMenuItem );
MenuItem SetupLocMenuItem = new MenuItem("Location");
//SetupLocMenuItem.Activated += new EventHandler(OnLocationClicked);
SetupMenu.Append( SetupLocMenuItem );
MenuItem SetupConMenuItem = new MenuItem("Container Entry");
//SetupConMenuItem.Activated += new EventHandler(OnContainerClicked);
SetupMenu.Append( SetupConMenuItem );
menubar1.Append(FileMenuItem);
menubar1.Append(SetupMenuItem);
//
this.Add( vbox1 );
vbox1.PackStart( menubar1, false, false, 0);
vbox1.PackStart( toolbar1, false, false, 0 );
vbox1.PackStart( vbox2, false, false, 0 );
vbox2.HeightRequest = 400;
vbox2.WidthRequest = 600;
vbox1.PackEnd( statusbar1, false, false, 0 );
toolbar1.Show();
menubar1.ShowAll();
this.ShowAll();
} //setup
An additional section of code describes the commands for
the toolbar buttons. Each button clears the main VBox area,then
initializes the class of the desired screen (e.g. Product Setup ), declares
the routine to be used for messages, and provide a message.
protected virtual void OnToolbutton1Clicked(object sender,
System.EventArgs e)
{
bool response = false;
response = AskDialog( "Do you really want to quit? " );
if ( response ) {
Application.Quit();
}
}
protected virtual void OnProductClicked(object sender, System.EventArgs e)
{
ClearVBox();
ProductSetup ps = new ProductSetup( vbox2, connect );
ps.ge.MessageReady += new MessageHandler( ShowMsg );
ShowMsg( "Loaded product rows: " + ps.ge.Rowcount );
}
protected virtual void OnLocationClicked(object sender, System.EventArgs e)
{
ClearVBox();
LocationSetup ls = new LocationSetup( vbox2, connect );
ls.ge.MessageReady += new MessageHandler( ShowMsg );
ShowMsg( "Loaded location rows: " + ls.ge.Rowcount );
}
protected virtual void OnContainerClicked(object sender, System.EventArgs e)
{
ClearVBox();
ContainerEntry ce = new ContainerEntry( vbox2, connect );
ce.ge.MessageReady += new MessageHandler( ShowMsg );
ShowMsg( "Loaded container rows: " + ce.ge.Rowcount );
}
protected virtual void OnClicked(object sender, System.EventArgs e)
{
ClearVBox();
}
void ClearVBox() {
Gtk.Widget[] w = vbox2.Children;
for(int i=0;i<w.GetUpperBound(0)+1;i++) {
vbox2.Remove( w[i] );
}
}
Here's the application running, and after I clicked the
closing button.

The MainWindow.cs File
Below is the entire file:
using System;
using Gtk;
using Gdk;
using System.Data;
using System.Data.Odbc;
using EntityLIB;
using TableGridLIB;
namespace Inventory
{
public class MainWindow: Gtk.Window
{
protected Gtk.VBox vbox1;
protected Gtk.MenuBar menubar1;
protected Gtk.Toolbar toolbar1;
protected Gtk.ToolButton toolbutton1;
protected Gtk.VBox vbox2;
protected Gtk.Statusbar statusbar1;
static string DSN = "DSN=inv;uid=root;pwd=;";
static OdbcConnection connect = new OdbcConnection( DSN );
public MainWindow (): base ("")
{
this.Resizable = false;
setup();
ShowMsg( "Welcome to Inventory" );
}
protected void OnDeleteEvent (object sender, DeleteEventArgs a)
{
bool response = false;
response = AskDialog( "Do you really want to quit? " );
if ( response ) {
Application.Quit();
}
a.RetVal = true;
}
protected virtual void OnToolbutton1Clicked(object sender, System.EventArgs
e)
{
bool response = false;
response = AskDialog( "Do you really want to quit? " );
if ( response ) {
Application.Quit();
}
}
protected virtual void OnProductClicked(object sender, System.EventArgs e)
{
ClearVBox();
ProductSetup ps = new ProductSetup( vbox2, connect );
ps.ge.MessageReady += new MessageHandler( ShowMsg );
ShowMsg( "Loaded product rows: " + ps.ge.Rowcount );
}
protected virtual void OnLocationClicked(object sender, System.EventArgs e)
{
ClearVBox();
LocationSetup ls = new LocationSetup( vbox2, connect );
ls.ge.MessageReady += new MessageHandler( ShowMsg );
ShowMsg( "Loaded location rows: " + ls.ge.Rowcount );
}
protected virtual void OnContainerClicked(object sender, System.EventArgs e)
{
ClearVBox();
ContainerEntry ce = new ContainerEntry( vbox2, connect );
ce.ge.MessageReady += new MessageHandler( ShowMsg );
ShowMsg( "Loaded container rows: " + ce.ge.Rowcount );
}
protected virtual void OnClicked(object sender, System.EventArgs e)
{
ClearVBox();
}
void ClearVBox() {
Gtk.Widget[] w = vbox2.Children;
for(int i=0;i<w.GetUpperBound(0)+1;i++) {
vbox2.Remove( w[i] );
}
}
void setup() {
AccelGroup m_AccelGroup = new AccelGroup();
this.Title = "Inventory";
this.DeleteEvent += new DeleteEventHandler (OnDeleteEvent);
this.AddAccelGroup(m_AccelGroup);
vbox2 = new VBox();
vbox1 = new VBox();
toolbar1 = new Gtk.Toolbar();
ToolButton toolbutton1 = new Gtk.ToolButton( "gtk-quit" );
toolbutton1.Label = "Quit";
toolbutton1.Clicked += new EventHandler( OnToolbutton1Clicked
);
toolbar1.Add( toolbutton1 );
ToolButton toolbutton2 = new Gtk.ToolButton( "gtk-dnd-multiple"
);
toolbutton2.Label = "Product";
toolbutton2.Clicked += new EventHandler( OnProductClicked );
toolbar1.Add( toolbutton2 );
ToolButton toolbutton3 = new Gtk.ToolButton( "gtk-indent" );
toolbutton3.Label = "Location";
toolbutton3.Clicked += new EventHandler( OnLocationClicked );
toolbar1.Add( toolbutton3 );
ToolButton toolbutton4 = new Gtk.ToolButton( "gtk-undelete"
);
toolbutton4.Label = "Container";
toolbutton4.Clicked += new EventHandler( OnContainerClicked
);
toolbar1.Add( toolbutton4 );
statusbar1 = new Gtk.Statusbar();
//
menubar1 = new MenuBar();
Menu FileMenu = new Menu();
MenuItem FileMenuItem = new MenuItem("_File");
FileMenuItem.Submenu = FileMenu;
MenuItem FileQuitMenuItem = new MenuItem("Quit");
FileQuitMenuItem.Activated += new
EventHandler(OnToolbutton1Clicked);
FileMenu.Append(FileQuitMenuItem);
Menu SetupMenu = new Menu();
MenuItem SetupMenuItem = new MenuItem("Setup");
SetupMenuItem.Submenu = SetupMenu;
MenuItem SetupProdMenuItem = new MenuItem("Product");
SetupProdMenuItem.Activated += new
EventHandler(OnProductClicked);
SetupMenu.Append( SetupProdMenuItem );
MenuItem SetupLocMenuItem = new MenuItem("Location");
SetupLocMenuItem.Activated += new
EventHandler(OnLocationClicked);
SetupMenu.Append( SetupLocMenuItem );
MenuItem SetupConMenuItem = new MenuItem("Container Entry");
SetupConMenuItem.Activated += new
EventHandler(OnContainerClicked);
SetupMenu.Append( SetupConMenuItem );
menubar1.Append(FileMenuItem);
menubar1.Append(SetupMenuItem);
//
this.Add( vbox1 );
vbox1.PackStart( menubar1, false, false, 0);
vbox1.PackStart( toolbar1, false, false, 0 );
vbox1.PackStart( vbox2, false, false, 0 );
vbox2.HeightRequest = 400;
vbox2.WidthRequest = 600;
vbox1.PackEnd( statusbar1, false, false, 0 );
toolbar1.Show();
menubar1.ShowAll();
this.ShowAll();
} //setup
bool AskDialog( string Message ) {
bool response = false;
MessageDialog md = new MessageDialog (
null,
DialogFlags.DestroyWithParent,
MessageType.Question,
ButtonsType.YesNo, Message );
int nRc = md.Run ();
if (nRc == (int)ResponseType.Yes) {
response = true;
md.Destroy();
} else {
response = false;
md.Destroy();
}
return response;
} //AskDialog
void ShowMsg( string Message ) {
statusbar1.Pop( 0 );
statusbar1.Push( 0, Message );
}
} //class
} //namespace
|