/// <summary>
		/// Initializes a new instance of the <see cref="OKHOSTING.ORM.UI.Forms.ObjectListPickerField"/> class.
		/// </summary>
		/// <summary xml:lang="es">
		/// Inicializa una nueva instancia de la clase OKHOSTING.ORM.UI.Forms.ObjectListPickerField, con un Select especificado.
		/// </summary>
		public ObjectAutoCompleteField(Select dataSource)
		{
			if (dataSource == null)
			{
				throw new ArgumentNullException(nameof(dataSource));
			}

			DataSource = dataSource;
		}
		/// <summary>
		/// Initializes a new instance of the <see cref="OKHOSTING.ORM.UI.Forms.ObjectListPickerField"/> class.
		/// <para xml:lang="es">
		/// Inicializa una nueva instancia de la clase OKHOSTING.ORM.UI.Forms.ObjectListPickerField, con un Select especificado.
		/// </para>
		/// </summary>
		public ObjectListPickerField(Select dataSource)
		{
			if (dataSource == null)
			{
				throw new ArgumentNullException(nameof(dataSource));
			}

			DataSource = dataSource;
		}
		public SelectController(Select dataSource)
		{
			if (dataSource == null)
			{
				throw new ArgumentNullException(nameof(dataSource));
			}

			DataSource = dataSource;
		}
		private 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();
		}
		/// <summary>
		/// It has the click event of the selected object.
		/// <para xml:lang="es">
		/// Contiene el evento clic del objeto seleccionado.
		/// </para>
		/// </summary>
		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;

			if (SelectController.DefaultSelects.ContainsKey(selected))
			{
				select = SelectController.DefaultSelects[selected];
			}
			else
			{
				select = new Select();
				select.DataType = selected;
				select.Limit = new SelectLimit(0, 20);
			}

			new SelectController(select).Start();
		}
		public void GenericOperations()
		{
			MapTypes();
			//Drop();
			//Create();

			for (int i = 0; i < 0; i++)
			{
				CustomerContact cc = new CustomerContact();
				cc.Firstname = "Fulanito " + i;
				cc.LastName = "De tal " + i;
				cc.BirthDate = DateTime.Now;
				
				cc.Customer = new Customer();
				cc.Customer.LegalName = "Cliente " + i;
				cc.Customer.Email = "Email " + i;
				
				cc.Address1 = new Address();
				cc.Address1.Street = "Calle " + i;
				cc.Address1.Number = "# " + i;
				cc.Address1.Country = new Country();
				cc.Address1.Country.Name = "Pais " + i;

				cc.Address2 = new Address();
				cc.Address2.Street = "2 Calle " + i;
				cc.Address2.Number = "2 # " + i;
				cc.Address2.Country = cc.Address1.Country;

				DataBase.Table<int, Country>().Add(0, cc.Address1.Country);
				DataBase.Table<int, Address>().Add(0, cc.Address1);
				DataBase.Table<int, Address>().Add(0, cc.Address2);
				DataBase.Table<int, Customer>().Add(0, cc.Customer);
				DataBase.Table<int, CustomerContact>().Add(0, cc);
			}

			Select<CustomerContact> select = new Select<CustomerContact>();
			select.AddMembers
			(
				c => c.Id, 
				c => c.BirthDate, 
				c => c.Customer.LegalName, 
				c=> c.Address1.Street, 
				c=> c.Address1.Country.Name,
				c=> c.Address2.Street,
				c=> c.Address2.Country.Name
			);

			var dtype = DataType<CustomerContact>.GetMap();
			select.Where.Add(new Filters.ValueCompareFilter()
			{
				Member = dtype[x => x.Id],
				ValueToCompare = 3,
				Operator = Data.CompareOperator.LessThanEqual,
			});
			
			select.OrderBy.Add(new Operations.OrderBy() { Member = dtype[x => x.Id], Direction = Data.SortDirection.Descending });

			var result = DataBase.Select<CustomerContact>(select).ToList();

			//Drop();
		}
		public void ComplexSelect()
		{
			MapTypes();
			Create();

			for (int i = 0; i < 20; i++)
			{
				CustomerContact contact = new CustomerContact();

				contact.Customer = new Customer();
				contact.Customer.LegalName = "Empresa " + i;
				contact.Customer.Phone = i.ToString();
				contact.Customer.Email = "*****@*****.**" + i;
				DataBase.Table<int, Customer>().Add(new KeyValuePair<int, Customer>(0, contact.Customer));

				contact.Firstname = "Argentina " + i;
				contact.LastName = "Chichona";
				contact.BirthDate = new DateTime(1980, 1, 1).AddDays(i);
				DataBase.Table<int, CustomerContact>().Add(new KeyValuePair<int, CustomerContact>(0, contact));
			}

			Select<CustomerContact> select = new Select<CustomerContact>();
			
			foreach (var member in select.DataType.DataMembers)
			{
				select.Members.Add(new Operations.SelectMember(member));
			}

			SelectJoin join = new SelectJoin();
			join.JoinType = SelectJoinType.Inner;
			join.Type = typeof(Customer);
			join.On.Add(new Filters.MemberCompareFilter(){ Member = select.DataType["Customer.Id"], MemberToCompare = join.Type["id"], Operator = Data.CompareOperator.Equal });
			select.Joins.Add(join);

			foreach (var member in join.Type.DataMembers.Where(m=> !m.Column.IsPrimaryKey))
			{
				select.Members.Add(new Operations.SelectMember(member));
			}

			foreach (CustomerContact e in DataBase.Select(select))
			{
				Console.WriteLine(e.Firstname + " " + e.Customer.LegalName);
			}

			Drop();
		}
		/// <summary>
		/// Start this instance, and load controls to edit data and the corresponding buttons.
		/// <para xml:lang="es">
		/// Inicia esta instancia y carga los controles de los datos a editar y de los botones correspondientes.
		/// </para>
		/// </summary>
		public override void Start()
		{
			base.Start();

			//add fields and populate values
			//Form.AddFieldsFrom(Instance);

			//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<IGrid>();
			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;

					if (SelectController.DefaultSelects.ContainsKey(foreignDataType))
					{
						select = SelectController.DefaultSelects[foreignDataType];
					}
					else
					{
						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<ILabelButton>();
					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<ILabelButton>();
					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;
		}
		public void ComplexSelect()
		{
			MapTypes();
			Create();

			for (int i = 0; i < 20; i++)
			{
				CustomerContact contact = new CustomerContact();

				contact.Customer = new Customer();
				contact.Customer.LegalName = "Empresa " + i;
				contact.Customer.Phone = i.ToString();
				contact.Customer.Email = "*****@*****.**" + i;
				//DataBase.Table<int, Customer>().Add(new KeyValuePair<int, Customer>(0, contact.Customer));
				DataBase.Insert(contact.Customer);

				contact.Firstname = "Argentina " + i;
				contact.LastName = "Chichona";
				contact.BirthDate = new DateTime(1980, 1, 1).AddDays(i);
				//DataBase.Table<int, CustomerContact>().Add(new KeyValuePair<int, CustomerContact>(0, contact));
				DataBase.Insert(contact);

			}


			Select<CustomerContact> select = new Select<CustomerContact>();
			select.AddMembers
			(
				c => c.Firstname,
				c => c.LastName,
				c => c.BirthDate,
				c => c.Customer.LegalName,
				c => c.Customer.Phone,
				c => c.Customer.Email
			);

			select.Limit = new SelectLimit(0, 10);

			foreach (CustomerContact e in DataBase.Select(select))
			{
				Console.WriteLine(e.Firstname + " " + e.Customer.LegalName);
			}

			Drop();
		}