OKHOSTING.ORM.UI

fondo-head

HOSTING DE ALTO PERFORMANCE

CONTRATAR AHORA
desarrollo-fondo

DESARROLLO DE APPS
MÓVILES

Millones de personas utilizan iPhone, iPad, Android y Windows Phone
No pierdas la oportunidad de llegar a este enorme mercado.
Tu aplicación móvil es la llave a este nuevo mundo de oportunidades.

Más información
SLIDE-DISENO-HOSTING
DOMINIOS DE INTERNET
¡REGISTRA TUS DOMINIOS WEB FACIL Y RAPIDO!
Más información
HEADER-ENCABEZADO
SERVIDORES DEDICADOS
FÍSICOS / VPS – TOMA EL CONTROL DE TUS DATOS
Más información
header-software

Ser eficiente, es ser diferente.
DESARROLLO DE SOFTWARE

Especializados en Cloud Software, desarrollamos sistemas y software de punta para tu empresa, Desarrollo de ERP, Sistemas administrativos, software de contabilidad, Inventarios, aplicaciones móviles y más

Más información
SLIDE-DISENOWEB

DISEÑO
DE PÁGINAS WEB

EXPERIENCIA E INNOVACIÓN
Tu sitio web en manos de profesionales, somos expertos en diseño, programación y medición de resultados.

Más información
header-tienda-online
TIENDAS EN LÍNEA
LA SOLUCIÓN COMPLETA PARA EL COMERCIO ELECTRÓNICO

Cree en tu potencial para vender por internet. Nosotros creamos tu tienda online y podrás comenzar a vender por internet, no importa si vendes ropa, dibujos, o maquinaria pesada, tenemos una solución para empieces a vender online.

Más información

1.- Introduccion

El OKHOSTING.ORM.UI, es un proyecto open source multiplataforma que nos ayuda de una manera muy fácil a crear interfaces de usuario para realizar operaciones de altas bajas y
consultas en una base de datos con OKHOSTING.UI.
Trabaja sobre OKHOSTING.Sql que nos da acceso a los motores de base de datos de MySQL, SQLite y “servicios web en base de datos” utilizado para móvil y MySql, SQLite, SQL
Server y PostgreSQL utilizado en proyectos de escritorio.
No es necesario el uso de clases especiales, se puede utilizar cualquier clase que ya tenga.
Es compatible con cualquier estrategia de herencia que desee y cualquier relación que necesite de uno a muchos o de muchos a muchos.
El proyecto OKHOSTING.ORM.UI nos permite trabajar con clases y tablas con nombres diferentes, al igual que las columnas de las tablas y las propiedades de las clases pueden
También tener nombres diferentes.
Este proyecto funciona en Windows, Linux, Mac, Android, iOS, Windows Phone y la plataforma universal de Windows.
El proyecto OKHOSTING.ORM.UI es muy rápido, ligero, pequeño y bastante fácil de usar.

2.- Instalacion

Para poder utilizar el proyecto OKHOSTING.ORM.UI basta con descargar e instalar los paquetes nuget OKHOSTING.ORM y OKHOSTING.ORM.UI.


PM> Install-Package OKHOSTING.ORM
PM> Install-Package OKHOSTING.ORM.UI

3.- Documentacion Tecnica

Para su mejor comprención, en esta sección, podrás consultar la documentación técnica de todo el proyecto OKHOSTING.ORM.UI.

4.- Requerimientos

Antes de comenzar a utilizar el proyecto OKHOSTING.ORM.UI, es necesario contar con los conocimientos basicos de C# y también manejar las sentencias basicas de SQL, ya que es
el lenguaje que utilizamos para el manejo de bases de datos.

5.- Aplicacion principal

Para utilizar el proyecto OKHOSTING.ORM.UI para realizar operaciones en una base de datos, tendremos que tener una base de datos ya creada y el modelo de clases que estarán
mapeadas a esta base de datos, para mayor información sobre como realizar el mapeo de las clases a una base de datos, consultar la página siguiente: OKHOSTING.ORM.UI

A continuación, mostramos un ejemplo de como funcionaría el proyecto con una base de datos:

Lo primero que hacemos en nuestra aplicación principal, es mandar llamar a nuestro IndexController y aquí también establecemos la conexión con la base de datos en el momento
que se requiera conectar a ella, esto lo hacemos tan sencillo con el código siguiente:


using OKHOSTING.ORM;
using OKHOSTING.UI.Net4.WebForms;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace OKHOSTING.School.UI.Net4.WebForms
{
public partial class Default : OKHOSTING.UI.Net4.WebForms.Page
{
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
OKHOSTING.ORM.DataBase.Setup += DataBase_Setup;
//page size is yet to be determined, since this is the first load
if (!IsPostBack && Width == 0 && Height == 0)
{
return;
}
if (Platform.Current.Controller == null)
{
new IndexController().Start();
}
}
private DataBase DataBase_Setup()
{
Core.Net4.AppConfig config = new Core.Net4.AppConfig();
return new DataBase(new Sql.Net4.MySql.DataBase() { ConnectionString = (string)config.GetValue("connectionString", typeof(string)) }, new Sql.MySql.SqlGenerator());
}
}
}

Que en el método DataBase_Setup(), obtenemos la conexión a la base de datos de nuestro archivo de configuración por medio de la variable “connectionString” y después
mandamos llamar al IndexController y a su método Start().


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OKHOSTING.UI;
using OKHOSTING.ORM;
using OKHOSTING.School;
using OKHOSTING.ORM.UI;
namespace OKHOSTING.School.UI
{
public class IndexController: Controller
{
public override void Start()
{
base.Start();
Type[] types = new Type[]
{
typeof(Student),
typeof(Subject),
typeof(Task),
typeof(Teacher),
};
//esto es para mapear las clases a tablas
DataType.DefaultMap(types).ToArray();
using (var db = DataBase.CreateDataBase())
{
DataType dtype = DataType.GetMap();
//create tables if they they doesnt exist yet
if (!db.NativeDataBase.ExistsTable(dtype.Table.Name))
{
db.Create(DataType.AllDataTypes);
}
}
new DataTypeListController().Start();
}
}
}

Que aquí lo que hacemos es hacer el mapeo de nuestras clases a la base de datos y después verificamos que exista alguna tabla en la base de datos, si no existe asumimos que no
existe ninguna tabla y las creamos todas y por último mandamos llamar al DataTypeListController y a su método Start(), que este lo que nos mostrara será una lista de los objetos
mapeados en la base de datos.
En nuestro caso y solo para este ejemplo estamos utilizando las clases siguientes con las propiedades mencionadas a continuación.
Student (Id, FirstName, LastName y Adres).
Subject (Id, Name y Teacher).
Task (Id, DeadLine, Teacher y Subject).
Teacher (Id, FirstName, LastName).

5.- Aplicacion principal

Para utilizar el proyecto OKHOSTING.ORM.UI para realizar operaciones en una base de datos, tendremos que tener una base de datos ya creada y el modelo de clases que estarán mapeadas a esta base de datos, para mayor información sobre como realizar el mapeo de las clases a una base de datos, consultar la página siguiente: OKHOSTING.ORM.UI A continuación, mostramos un ejemplo de como funcionaría el proyecto con una base de datos: Lo primero que hacemos en nuestra aplicación principal, es mandar llamar a nuestro IndexController y aquí también establecemos la conexión con la base de datos en el momento que se requiera conectar a ella, esto lo hacemos tan sencillo con el código siguiente:

using OKHOSTING.ORM;
using OKHOSTING.UI.Net4.WebForms;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace OKHOSTING.School.UI.Net4.WebForms
{
public partial class Default : OKHOSTING.UI.Net4.WebForms.Page
{
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
OKHOSTING.ORM.DataBase.Setup += DataBase_Setup;
//page size is yet to be determined, since this is the first load
if (!IsPostBack && Width == 0 && Height == 0)
{
return;
}
if (Platform.Current.Controller == null)
{
new IndexController().Start();
}
}
private DataBase DataBase_Setup()
{
Core.Net4.AppConfig config = new Core.Net4.AppConfig();
return new DataBase(new Sql.Net4.MySql.DataBase() { ConnectionString = (string)config.GetValue("connectionString", typeof(string)) }, new Sql.MySql.SqlGenerator());
}
}
}
Que en el método DataBase_Setup(), obtenemos la conexión a la base de datos de nuestro archivo de configuración por medio de la variable "connectionString" y después mandamos llamar al IndexController y a su método Start().

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OKHOSTING.UI;
using OKHOSTING.ORM;
using OKHOSTING.School;
using OKHOSTING.ORM.UI;
namespace OKHOSTING.School.UI
{
public class IndexController: Controller
{
public override void Start()
{
base.Start();
Type[] types = new Type[]
{
typeof(Student),
typeof(Subject),
typeof(Task),
typeof(Teacher),
};
//esto es para mapear las clases a tablas
DataType.DefaultMap(types).ToArray();
using (var db = DataBase.CreateDataBase())
{
DataType dtype = DataType.GetMap();
//create tables if they they doesnt exist yet
if (!db.NativeDataBase.ExistsTable(dtype.Table.Name))
{
db.Create(DataType.AllDataTypes);
}
}
new DataTypeListController().Start();
}
}
}
Que aquí lo que hacemos es hacer el mapeo de nuestras clases a la base de datos y después verificamos que exista alguna tabla en la base de datos, si no existe asumimos que no existe ninguna tabla y las creamos todas y por último mandamos llamar al DataTypeListController y a su método Start(), que este lo que nos mostrara será una lista de los objetos mapeados en la base de datos. En nuestro caso y solo para este ejemplo estamos utilizando las clases siguientes con las propiedades mencionadas a continuación. Student (Id, FirstName, LastName y Adres). Subject (Id, Name y Teacher). Task (Id, DeadLine, Teacher y Subject). Teacher (Id, FirstName, LastName).

5.1. Ejemplo del DataTypeListController

Como ya mencionaba anteriormente, en el control DataTypeListController, lo que mostramos es la lista de nuestros objetos mapeados a la base de datos, cada uno como un link
donde al momento de seleccionar alguno, nos mandara a la lista de los DataTypes de este objeto, donde podemos realizar cualquier operación en la base de datos sobre este objeto
y esto lo hace tan fácil como el código siguiente:


using OKHOSTING.ORM.Operations;
using OKHOSTING.UI;
using OKHOSTING.UI.Controls;
using OKHOSTING.UI.Controls.Layout;
using System;
using System.Collections.Generic;
using System.Linq;
namespace OKHOSTING.ORM.UI
{
public class DataTypeListController: Controller
{
public IEnumerable DataTypes { get; set; }
public override void Start()
{
base.Start();
if (DataTypes == null || !DataTypes.Any())
{
DataTypes = DataType.AllDataTypes;
}
IStack list = Platform.Current.Create();
foreach (DataType dtype in DataTypes)
{
ILabelButton link = Platform.Current.Create();
link.Text = Translator.Translate(dtype.InnerType);
link.Click += Link_Click;
list.Children.Add(link);
}
Platform.Current.Page.Title = Resources.Strings.OKHOSTING_ORM_UI_DataTypeListController_Title;
Platform.Current.Page.Content = list;
}
protected virtual void Link_Click(object sender, EventArgs e)
{
ILabelButton clicked = (ILabelButton) sender;
DataType selected = DataType.AllDataTypes.Where(dt => Translator.Translate(dt.InnerType) == clicked.Text).Single();
Select select = new Select();
select.DataType = selected;
select.Limit = new SelectLimit(0, 20);
new SelectController(select).Start();
}
}
}

Donde lo primero que hacemos es crear un link o un ILabelButton para cada objeto mapeado y después en el evento clic de cada objeto, lo que hacemos es realizar un select de este
objeto y después mandamos llamar al control SelectController pasándole como parametro el select que hemos realizado anteriormente.

La lista de objetos se mirarían de esta manera en un webform:

 

ListaObjetosWebForm

De esta manera en un WinForm:

ListObjectsWinForm

y de esta manera en un WPF:

ListObjectsWPF

Cabe mencionar que para cada control le podemos dar diseño al gusto que queramos este ejemplo es algo muy basico.

5.2 Ejemplo de un SelectController

En el SelectController, lo que hacemos es mostrar la lista de los DataTypes que contiene el objeto seleccionado y también mostramos las opciones de las operaciones que podemos
realizar sobre algún DataType del objeto, esto lo hacemos muy fácil solo con el código siguiente:


using OKHOSTING.ORM.Operations;
using OKHOSTING.ORM.UI.Forms;
using OKHOSTING.UI;
using OKHOSTING.UI.Controls;
using OKHOSTING.UI.Controls.Layout;
using System;
using System.Linq;
using System.Collections.Generic;
namespace OKHOSTING.ORM.UI
{
public class SelectController : Controller
{
public readonly Select DataSource;
protected ObjectGrid Grid;
protected FilterDataForm frmFilters;
protected int PageSize = 20;
protected int CurrentPage = 1;
protected ILabel lblTotal;
protected IListPicker lstCurrentPage;
protected List<ICheckBox> SelectChecks;
public SelectController(Select dataSource)
{
if (dataSource == null)
{
throw new ArgumentNullException(nameof(dataSource));
}
DataSource = dataSource;
}
public override void Start()
{
base.Start();
Grid = new ObjectGrid();
Grid.Sorted += Grid_Sorted;
SelectChecks = new List<ICheckBox>();
lblTotal = Platform.Current.Create<ILabel>();
//page size
ILabel lblPageSize = Platform.Current.Create<ILabel>();
lblPageSize.Text = "Page size:";
IListPicker lstPageSize = Platform.Current.Create<IListPicker>();
lstPageSize.Items = new List<string>() { "20", "50", "100", "200", "500", "1000" };
lstPageSize.Value = "20";
lstPageSize.ValueChanged += LstPageSize_ValueChanged;
//current page
ILabel lblCurrentPage = Platform.Current.Create<ILabel>();
lblCurrentPage.Text = "Current page:";
lstCurrentPage = Platform.Current.Create<IListPicker>();
lstCurrentPage.ValueChanged += LstCurrentPage_ValueChanged;
//add New button
IListPicker cmdNewRecord = Platform.Current.Create<IListPicker>();
cmdNewRecord.Items = new List<string>();
cmdNewRecord.Items.Add(Resources.Strings.OKHOSTING_ORM_UI_SelectController_New);
cmdNewRecord.Items.Add(Translator.Translate(DataSource.DataType.InnerType));
foreach(DataType dtype in DataSource.DataType.SubDataTypesRecursive)
{
cmdNewRecord.Items.Add(Translator.Translate(dtype.InnerType));
}
cmdNewRecord.ValueChanged += cmdNewRecord_ValueChanged;
//add Back button
IButton cmdBack = Platform.Current.Create<IButton>();
cmdBack.Text = Resources.Strings.OKHOSTING_ORM_UI_SelectController_Back;
cmdBack.Click += Back_Click;
//grid.content is created here
Refresh();
//now create  the filters form with the same number of columns as the grid
frmFilters = new FilterDataForm();
frmFilters.RepeatColumns = Grid.DataSource.Members.Count;
foreach (var memberInfo in DataSource.DataType.AllMemberInfos)
{
frmFilters.AddFields(memberInfo);
}
frmFilters.DataBind();
foreach (Filters.Filter filter in DataSource.Where)
{
frmFilters.ApplyFilter(filter);
}
//buton to apply filter
IButton cmdRefresh = Platform.Current.Create<IButton>();
cmdRefresh.Text = "Refresh";
cmdRefresh.Click += cmdFilter_Click;
//buton to delete selected objects
IButton cmdDelete = Platform.Current.Create<IButton>();
cmdDelete.Text = "Delete";
cmdDelete.Click += cmdDelete_Click;
//create our own grid
IGrid container = Platform.Current.Create<IGrid>();
container.ColumnCount = 9;
container.RowCount = 4;
container.SetContent(0, 0, frmFilters.Content);
container.SetColumnSpan(7, frmFilters.Content);
container.SetContent(2, 0, cmdRefresh);
container.SetContent(2, 1, cmdNewRecord);
container.SetContent(2, 2, cmdBack);
container.SetContent(2, 3, cmdDelete);
container.SetContent(2, 4, lblPageSize);
container.SetContent(2, 5, lstPageSize);
container.SetContent(2, 6, lblCurrentPage);
container.SetContent(2, 7, lstCurrentPage);
container.SetContent(2, 8, lblTotal);
container.SetContent(3, 0, Grid.Content);
container.SetColumnSpan(container.ColumnCount, Grid.Content);
Platform.Current.Page.Title = Resources.Strings.OKHOSTING_ORM_UI_SelectController_List + ' ' + Translator.Translate(DataSource.DataType.InnerType);
Platform.Current.Page.Content = container;
}
private void Grid_Sorted(object sender, EventArgs e)
{
AddCheckBoxes();
}
private void cmdNewRecord_ValueChanged(object sender, string e)
{
IListPicker lstNewRecord = (IListPicker) sender;
DataType dtype;
if (lstNewRecord.Value == Resources.Strings.OKHOSTING_ORM_UI_SelectController_New)
{
return;
}
if (Translator.Translate(DataSource.DataType.InnerType) == lstNewRecord.Value)
{
dtype = DataSource.DataType.InnerType;
}
else
{
dtype = DataSource.DataType.SubDataTypesRecursive.Where(dt => Translator.Translate(dt.InnerType) == lstNewRecord.Value).Single();
}
object instance = Activator.CreateInstance(dtype.InnerType);
//use filters as default values, in case they are a foreign key
foreach (Filters.ValueCompareFilter filter in DataSource.Where.Where(f => f is Filters.ValueCompareFilter))
{
if (filter.Operator != Data.CompareOperator.Equal)
{
continue;
}
filter.Member.Expression.SetValue(instance, filter.ValueToCompare);
}
new InsertController(instance).Start();
}
private void cmdDelete_Click(object sender, EventArgs e)
{
Delete delete = new Delete();
List<object> instances;
List<object> selected;
using (var db = DataBase.CreateDataBase())
{
instances = db.Select(DataSource).ToList();
}
//now choose only selected records
selected = new List<object>();
foreach (ICheckBox chkSelect in SelectChecks.Where(chk => chk.Value))
{
int index = int.Parse(chkSelect.Name.Substring(nameof(chkSelect).Length + 1));
if (index == 0)
{
continue;
}
selected.Add(instances[index - 1]);//skip header
}
//go to delete controller
new DeleteController(selected).Start();
}
private void cmdFilter_Click(object sender, EventArgs e)
{
//backup default filters
DataSource.Where.Clear();
CurrentPage = 1;
foreach(var member in DataSource.DataType.AllMemberInfos)
{
var filter = frmFilters.GetFilter(member);
if(filter != null)
{
DataSource.Where.Add(filter);
}
}
Refresh();
}
public override void Refresh()
{
base.Refresh();
//show total records
SelectAggregate count = new SelectAggregate();
count.DataType = DataSource.DataType;
count.Where.AddRange(DataSource.Where);
count.Joins.AddRange(DataSource.Joins);
count.AggregateMembers.Add(new SelectAggregateMember(DataSource.DataType.PrimaryKey.First(), SelectAggregateFunction.Count));
int totalRecords = 0;
using (var db = DataBase.CreateDataBase())
{
totalRecords = Data.Convert.ChangeType<int>(db.SelectScalar(count));
}
lblTotal.Text = "Total records: " + totalRecords;
//populate current page picker
lstCurrentPage.Items = new List<string>();
int page = 1;
do
{
lstCurrentPage.Items.Add(page.ToString());
page++;
}
while ((page - 1) * PageSize <= totalRecords);
lstCurrentPage.Value = CurrentPage.ToString();
//set paging
DataSource.Limit = new SelectLimit((CurrentPage - 1) * PageSize, PageSize);
//rebuild data grid
Grid.DataSource = DataSource;
Grid.DataBind();
AddCheckBoxes();
}
private void AddCheckBoxes()
{
Grid.Content.ColumnCount++;
SelectChecks.Clear();
for (int row = 0; row < Grid.Content.RowCount; row++)
{
ICheckBox chkSelect = Platform.Current.Create<ICheckBox>();
chkSelect.Name = nameof(chkSelect) + "_" + row;
Grid.Content.SetContent(row, Grid.Content.ColumnCount - 1, chkSelect);
if (row == 0)
{
chkSelect.ValueChanged += ChkSelect_ValueChanged;
}
SelectChecks.Add(chkSelect);
}
}
private void ChkSelect_ValueChanged(object sender, bool e)
{
foreach (ICheckBox chk in SelectChecks)
{
chk.Value = ((ICheckBox) sender).Value;
}
}
private void LstCurrentPage_ValueChanged(object sender, string e)
{
CurrentPage = int.Parse(((IListPicker) sender).Value);
Refresh();
}
private void LstPageSize_ValueChanged(object sender, string e)
{
PageSize = int.Parse(((IListPicker)sender).Value);
CurrentPage = 1;
Refresh();
}
private void Back_Click(object sender, EventArgs e)
{
Finish();
}
}
}

En esta parte mostramos la lista de los DataTypes que contiene el objeto seleccionado en forma de link, nos muestra también como información el número de registros que contiene
el objeto seleccionado y también mostramos las opciones que nos permiten realizar las operaciones en la base de datos sobre el objeto seleccionado.

Así que se miraría de esta manera en webform:

 

ListDataTypes

De esta manera en WinForm:

ListTaskWinForm

Y de esta manera en WPF:

ListTaskWPF

Por ejemplo si damos clic en el input que dice “Create New” y seleccionamos el objeto que queremos crear, nos manda al InsertController, pasándole como parametro, la
instancia del objeto seleccionado.
Si seleccionamos el CheckBox de un DataType y le damos clic en el botón de Delete, nos manda a una pantalla donde nos pide confirmar que queremos eliminar el elemento
seleccionado, o también podemos eliminar todos los registros existentes solo bastaría con seleccionarlos todos.
Si le damos clic a alguno de los elementos que nos muestra en la lista, nos manda a un UpdateController, donde podemos editar los datos del elemento seleccionado.
Si damos clic en el botón de Refresh, lo que hace es refrescarnos la vista por si se ha borrado o editado algún elemento.
El SelectController, también nos permite realizar filtros de la información, por ejemplo en este caso, podemos filtrar nuestra información por medio de un rango de
fechas, por un rango de Id’s, por Subject o por Teacher, agilizándonos el manejo de la información en el caso de que sea un gran volumen.

5.3 Ejemplo de un InsertController

En el InsertController, lo que hacemos es mostrar una lista de controles que nos permiten introducir los datos del objeto mediante la entrada del usuario, tambien muestra los
botones para guardar los datos y el de cancelar para cancelar la operación esto lo hace tan sencillo como el código siguiente.


using OKHOSTING.Data.Validation;
using OKHOSTING.ORM.UI.Forms;
using OKHOSTING.UI;
using OKHOSTING.UI.Controls;
using OKHOSTING.UI.Controls.Layout;
using System;
using System.Reflection;
namespace OKHOSTING.ORM.UI
{
public class InsertController: Controller
{
public readonly DataType DataType;
protected readonly object Instance;
protected readonly ObjectForm Form;
protected ILabel lblMessages;
public InsertController(DataType dataType)
{
if (dataType == null)
{
throw new ArgumentNullException(nameof(dataType));
}
DataType = dataType;
Instance = Activator.CreateInstance(DataType.InnerType);
Form = new ObjectForm();
}
public InsertController(object instance)
{
if (instance == null)
{
throw new ArgumentNullException(nameof(instance));
}
DataType = instance.GetType();
Instance = instance;
Form = new ObjectForm();
}
public override void Start()
{
base.Start();
DataType dtype = Instance.GetType();
using (var db = DataBase.CreateDataBase())
{
//create fields
foreach (MemberInfo member in dtype.AllMemberInfos)
{
//ignore primary key if it's AutoIncrement or Guid or static
if (dtype.IsMapped(member.Name) && (dtype[member.Name].Column.IsAutoNumber || dtype[member.Name].Column.DbType == Sql.DbType.Guid))
{
continue;
}
OKHOSTING.UI.Controls.Forms.FormField field = Form.AddField(member);
field.ValueControl.Name = "fld" + member.Name;
}
//actually create the form
Form.DataBind();
foreach (MemberInfo member in dtype.AllMemberInfos)
{
//ignore primary key if it's AutoIncrement or Guid or static
if (dtype.IsMapped(member.Name) && (dtype[member.Name].Column.IsAutoNumber || dtype[member.Name].Column.DbType == Sql.DbType.Guid))
{
continue;
}
OKHOSTING.UI.Controls.Forms.FormField field = Form[member];
var value = MemberExpression.GetValue(member, Instance);
if (value != null)
{
if (DataType.IsMapped(value.GetType()))
{
db.Select(value);
}
field.Value = value;
}
}
}
//add Save button
IButton cmdSave = Platform.Current.Create<IButton>();
cmdSave.Text = Resources.Strings.OKHOSTING_ORM_UI_InsertController_Save;
cmdSave.Click += cmdSave_Click;
//add Cancel button
IButton cmdCancel = Platform.Current.Create<IButton>();
cmdCancel.Text = Resources.Strings.OKHOSTING_ORM_UI_InsertController_Cancel;
cmdCancel.Click += cmdCancel_Click;
//add label for error messages
lblMessages = Platform.Current.Create<ILabel>();
lblMessages.Visible = false;
//create our own grid
//create our own grid
IGrid grid = Platform.Current.Create();
grid.ColumnCount = 3;
grid.RowCount = 3;
grid.SetContent(0, 0, Form.Content);
grid.SetColumnSpan(2, Form.Content);
grid.SetContent(1, 0, cmdSave);
grid.SetContent(1, 1, cmdCancel);
grid.SetContent(2, 0, lblMessages);
grid.SetColumnSpan(2, lblMessages);
Platform.Current.Page.Title = Resources.Strings.OKHOSTING_ORM_UI_InsertController_New + ' ' + Translator.Translate(DataType.InnerType);
Platform.Current.Page.Content = grid;
}
private void cmdCancel_Click(object sender, EventArgs e)
{
Finish();
}
private void cmdSave_Click(object sender, EventArgs e)
{
lblMessages.Visible = false;
Form.CopyValuesTo(Instance);
using (var db = DataBase.CreateDataBase())
{
db.NativeDataBase.BeginTransaction();
try
{
db.InsertAll(Instance);
}
catch (Exception ex)
{
db.NativeDataBase.RollBackTransaction();
lblMessages.Visible = true;
lblMessages.Text = "Error: " + ex;
return;
}
db.NativeDataBase.CommitTransaction();
}
Finish();
}
}
}

Asi se miraria en un WebForm:

NewTaskWebForm

De esta manera en un WinForm:

NewTaskWinForm

Y de esta manera en un WPF:

NewTaskWPF

En este caso, estamos dando de alta un “Task” nuevo.
Lo que hace el código es crear un campo por cada propiedad del objeto para introducir la informacion necesaria que se requiere almacenar, asi como tambien un label que descrive
a la propiedad del objeto, despues crea el boton de guardar para guardar los datso y el de cancelar para cancelar la operacion.
Al dar clic en el boton de guardar nos regresa al SelectController, donde al dar clic en Refresh, nos agrega el nuebo elemento guardado, sin damos clic en cancelar, de la misma
manera nos direcciona al SelectController pero sin mostrar ningun cambio.

5.4 Ejemplo de un DeleteController

Al dar clic en el botón Delete, intentando eliminar uno o barios elementos, nos envía a un DeleteController, donde lo que hace es mostrar un mensaje con un CheckBox donde nos
pide confirmar la eliminación del o los elementos seleccionados y también nos muestra los botones de aceptar y cancelar, lo cual hace por medio del siguiente codigo:


using OKHOSTING.ORM.UI.Forms;
using OKHOSTING.UI;
using OKHOSTING.UI.Controls;
using OKHOSTING.UI.Controls.Layout;
using System;
using System.Linq;
using System.Collections.Generic;
namespace OKHOSTING.ORM.UI
{
public class DeleteController : Controller
{
protected readonly Operations.Delete Delete;
protected ICheckBox chkConfirm;
protected ILabel lblConfirm;
protected ILabel lblMessages;
public DeleteController(object instance)
{
if (instance == null)
{
throw new ArgumentNullException(nameof(instance));
}
Delete = new Operations.Delete();
Delete.DataType = instance.GetType();
Delete.Where.Add(new Filters.PrimaryKeyFilter(instance));
}
public DeleteController(IEnumerable<object> instances)
{
if (instances == null || !instances.Any())
{
throw new ArgumentNullException(nameof(instances));
}
Delete = new Operations.Delete();
Delete.DataType = instances.First().GetType();
Filters.OrFilter or = new Filters.OrFilter();
foreach (object instance in instances)
{
or.InnerFilters.Add(new Filters.PrimaryKeyFilter(instance));
}
Delete.Where.Add(or);
}
public DeleteController(Operations.Delete delete)
{
if (delete == null)
{
throw new ArgumentNullException(nameof(delete));
}
Delete = delete;
}
public override void Start()
{
base.Start();
//add label with instance names, select from database
ILabel lblInstanceNames = Platform.Current.Create<ILabel>();
lblInstanceNames.Text = string.Empty;
Operations.Select select = new Operations.Select();
select.DataType = Delete.DataType;
select.Where.AddRange(Delete.Where);
int count = 0;
using (var db = DataBase.CreateDataBase())
{
foreach(object instance in db.Select(select))
{
lblInstanceNames.Text += instance.ToString() + "\n";
count++;
}
}
lblInstanceNames.Text = count + " records will be deleted:\n\n" + lblInstanceNames.Text;
//add confirmation checkbox
lblConfirm = Platform.Current.Create<ILabel>();
lblConfirm.Text = Resources.Strings.OKHOSTING_ORM_UI_DeleteController_Confirm;
chkConfirm = Platform.Current.Create<ICheckBox>();
//add delete button
IButton delete = Platform.Current.Create<IButton>();
delete.Text = Resources.Strings.OKHOSTING_ORM_UI_DeleteController_Delete;
delete.Click += Delete_Click;
//add Cancel button
IButton cancel = Platform.Current.Create<IButton>();
cancel.Text = Resources.Strings.OKHOSTING_ORM_UI_UpdateController_Cancel;
cancel.Click += Cancel_Click;
//add label for error messages
lblMessages = Platform.Current.Create<ILabel>();
lblMessages.Visible = false;
//create our own grid
IGrid grid = Platform.Current.Create<IGrid>();
grid.ColumnCount = 2;
grid.RowCount = 4;
grid.SetContent(0, 0, lblInstanceNames);
grid.SetColumnSpan(2, lblInstanceNames);
grid.SetContent(1, 0, lblConfirm);
grid.SetContent(1, 1, chkConfirm);
grid.SetContent(2, 0, delete);
grid.SetContent(2, 1, cancel);
grid.SetContent(3, 0, lblMessages);
grid.SetColumnSpan(2, lblMessages);
Platform.Current.Page.Title = Resources.Strings.OKHOSTING_ORM_UI_DeleteController_Delete + ' ' + Translator.Translate(Delete.DataType.InnerType);
Platform.Current.Page.Content = grid;
}
private void Delete_Click(object sender, EventArgs e)
{
if (!chkConfirm.Value)
{
lblConfirm.FontColor = new Color(255, 255, 0, 0);
return;
}
using (var db = DataBase.CreateDataBase())
{
db.NativeDataBase.BeginTransaction();
try
{
db.Delete(Delete);
}
catch (Exception ex)
{
db.NativeDataBase.RollBackTransaction();
lblMessages.Visible = true;
lblMessages.Text = "Error: " + ex;
return;
}
db.NativeDataBase.CommitTransaction();
}
Finish();
}
private void Cancel_Click(object sender, EventArgs e)
{
//Ends the current instance
Finish();
}
}
}

De esta manera se miraria en un WebForm:

BorrarWebForm

De esta manera en un WinForm:

DeleteSubjectWinForm

Y de esta manera en un WPF:

DeleteSubjectWPF

Así que al confirmar la operación y dar clic en el botón de delete, nos regresa al SelectControler, donde al dar clic al botón refresh, nos refresca la vista mostrando solo los
elementos que no fueron borrados, o la vista vacía en el caso de que hayamos borrado todos los elementos, por lo contrario si damos clic en el botón de cancelar, de igual
manera nos redirecciona al SelectControler pero sin hacer ninguna modificación en la vista.

5.5 Ejemplo del UpdateController

Cuando estamos en el SelectController, al dar clic en algún elemento de la lista del objeto, nos manda a un UpdateController, donde podemos editar los datos del elemento
seleccionado, también nos muestra un botón de guardar, otro de cancelar y otro de borrar.
Esto lo hace solo con el código siguiente:


using OKHOSTING.UI;
using OKHOSTING.UI.Controls;
using OKHOSTING.UI.Controls.Layout;
using System;
using System.Linq;
using System.Reflection;
namespace OKHOSTING.ORM.UI
{
public class UpdateController : Controller
{
public readonly object Instance;
public readonly DataType DataType;
protected readonly ObjectForm Form;
protected ILabel lblMessages;
public UpdateController(object instance)
{
if (instance == null)
{
throw new ArgumentNullException(nameof(instance));
}
using (var db = DataBase.CreateDataBase())
{
Instance = db.SelectInherited(instance).Last();
}
DataType = Instance.GetType();
Form = new ObjectForm();
Form.RepeatColumns = 4;
}
public override void Start()
{
base.Start();
//create fields
foreach (MemberInfo member in DataType.AllMemberInfos)
{
//ignore primary key if it's AutoIncrement or Guid or static
if (DataType.IsMapped(member.Name) && (DataType[member.Name].Column.IsAutoNumber || DataType[member.Name].Column.DbType == Sql.DbType.Guid))
{
continue;
}
OKHOSTING.UI.Controls.Forms.FormField field = Form.AddField(member);
field.ValueControl.Name = "fld" + member.Name;
}
//actually create the form
Form.DataBind();
using (var db = DataBase.CreateDataBase())
{
foreach (MemberInfo member in DataType.AllMemberInfos)
{
//ignore primary key if it's AutoIncrement or Guid or static
if (DataType.IsMapped(member.Name) && (DataType[member.Name].Column.IsAutoNumber || DataType[member.Name].Column.DbType == Sql.DbType.Guid))
{
continue;
}
OKHOSTING.UI.Controls.Forms.FormField field = Form[member];
var value = MemberExpression.GetValue(member, Instance);
if (value != null)
{
if (DataType.IsMapped(value.GetType()))
{
db.Select(value);
}
field.Value = value;
}
}
}
//add Save button
IButton cmdSave = Platform.Current.Create<IButton>();
cmdSave.Text = Resources.Strings.OKHOSTING_ORM_UI_UpdateController_Save;
cmdSave.Click += Save_Click;
//add Cancel button
IButton cmdCancel = Platform.Current.Create<IButton>();
cmdCancel.Text = Resources.Strings.OKHOSTING_ORM_UI_UpdateController_Cancel;
cmdCancel.Click += Cancel_Click;
//add Delete button
IButton cmdDelete = Platform.Current.Create<IButton>();
cmdDelete.Text = Resources.Strings.OKHOSTING_ORM_UI_UpdateController_Delete;
cmdDelete.Click += Delete_Click;
//add label for error messages
lblMessages = Platform.Current.Create<ILabel>();
lblMessages.Visible = false;
//create our own grid
IGrid grid = Platform.Current.Create();
grid.ColumnCount = 3;
grid.RowCount = 3;
grid.SetContent(0, 0, Form.Content);
grid.SetColumnSpan(3, Form.Content);
grid.SetContent(1, 0, cmdSave);
grid.SetContent(1, 1, cmdCancel);
grid.SetContent(1, 2, cmdDelete);
grid.SetContent(2, 0, lblMessages);
grid.SetColumnSpan(3, lblMessages);
var dtype = DataType;
while (dtype != null)
{
//create links for collections, if any
foreach (MemberInfo member in dtype.InboundForeingKeys)
{
DataType foreignDataType = member.DeclaringType;
Select select = new Select();
select.DataType = foreignDataType;
select.Limit = new SelectLimit(0, 20);
select.Where.Add(new ForeignKeyFilter(foreignDataType, member, Instance));
ILabelButton lbbCollection = Platform.Current.Create();
lbbCollection.Text = Translator.Translate(foreignDataType.InnerType) + "." + Translator.Translate(member);
lbbCollection.Tag = select;
lbbCollection.Click += lbbCollection_Click;
grid.RowCount++;
grid.SetContent(grid.RowCount - 1, 0, lbbCollection);
}
//create links for methods, if any
foreach (MethodInfo method in dtype.InnerType.GetTypeInfo().DeclaredMethods)
{
//ignore static and property methods
if (method.IsStatic || method.Name.StartsWith("get_") || method.Name.StartsWith("set_"))
{
continue;
}
ILabelButton lbbMethod = Platform.Current.Create();
lbbMethod.Text = Core.TypeExtensions.GetFriendlyFullName(method);
lbbMethod.Tag = method;
lbbMethod.Click += lbbMethod_Click; ;
grid.RowCount++;
grid.SetContent(grid.RowCount - 1, 0, lbbMethod);
}
dtype = dtype.BaseDataType;
}
Platform.Current.Page.Title = Resources.Strings.OKHOSTING_ORM_UI_UpdateController_Update + ' ' + Translator.Translate(this.DataType.InnerType);
Platform.Current.Page.Content = grid;
}
private void lbbMethod_Click(object sender, EventArgs e)
{
MethodInfo method = (MethodInfo) ((IControl) sender).Tag;
new MethodController(method, Instance).Start();
}
private void lbbCollection_Click(object sender, EventArgs e)
{
Select select = (Select) ((IControl) sender).Tag;
new SelectController(select).Start();
}
private void Delete_Click(object sender, EventArgs e)
{
new DeleteController(Instance).Start();
}
private void Cancel_Click(object sender, EventArgs e)
{
Finish();
}
private void Save_Click(object sender, EventArgs e)
{
Form.CopyValuesTo(Instance);
using (var db = DataBase.CreateDataBase())
{
db.NativeDataBase.BeginTransaction();
try
{
//make sure any foreign key or collection item is saved
db.InsertAll(Instance);
//now just update the instance
db.Update(Instance);
}
catch (Exception ex)
{
db.NativeDataBase.RollBackTransaction();
lblMessages.Visible = true;
lblMessages.Text = "Error: " + ex;
return;
}
db.NativeDataBase.CommitTransaction();
}
Finish();
}
}
}

De esta manera, al introducir los nuevos datos en los controles correspondientes y al dar clic en el botón de guardar, nos manda al SelectController, que al dar clic en refrescar,
nos mostrara ya el elemento editado con sus nuevos datos, si damos clic en cancelar, nos direcciona de igual manera al SelectController pero sin cambiar ningún elemento y si
de lo contrario, damos clic en el botón de borrar, nos direcciona al DeleteController, donde nos pide confirmar el borrado del elemento en cuestión.

Asi que de esta manera es como se miraría la edicion de un “Subject” en un WebForm:

EditSubjectWebForm

De esta manera se miraria la edicion de un “Task” en un WinForm:

EditTask

Y asi se miraria en un WPF:

EditTaskWPF

Como ya lo comentabamos anteriormente, este es un ejemplo muy basico y muy sencillo, pero a todos los controles se les puede dar el diseño que queramos a nuestro gusto y
tambien podemos usar cualquier control que usamos en estos ejemplos cada uno por separado, ya sea el IGrid, el ILabel, IButton, ILabelButton, etc. en la vista que queramos
y con el diseño que queramos.

Contáctanos
Platícanos tus requerimientos
¡Te responderemos a la brevedad!
:: +5233 3618 8825

:: ventas@okhosting.com
Escríbenos

SOLICITAR COTIZACIÓN