jueves, 13 de noviembre de 2014

Implementar una caja de texto y un calendario en una página web

Para implementar la funcionalidad de una caja de texto y la selección de la fecha con un control de calendario se puede hacer de lo siguiente:


  • Crear la caja de texto y el control de calendario en la forma y asignarles el atributo ClientInstanceName para poder nombrarlos con javascript en el lado del cliente.
  • Agregar el atributo ClientVisible al control de calendario y ponerlo en false para que no esté visible en el cliente.
  • Agregar el evento GotFocus a la caja de texto .
  • Agregar el evento OnSelectionChanged para el control de calendario.
El markup de estos controles debe quedar así:


<dx:ASPxTextBox ID="txtRequiredDate" runat="server" Width="170px" ClientInstanceName="txtRequiredDate">
     <ClientSideEvents GotFocus="OnGotFocus" />
</dx:ASPxTextBox>

<dx:ASPxCalendar ID="calRequiredDate" runat="server" ClientInstanceName="calRequiredDate" ClientVisible="false">
     <ClientSideEvents SelectionChanged="OnSelectionChanged" />
</dx:ASPxCalendar>


  • Luego hay que agregar el código javascript necesario para mostrar el calendario, para obtener la fecha y ponerla en la caja de texto y para volver a esconderlo. Esto debe quedar de la siguiente manera:

<script language="javascript" type="text/javascript">
    function OnGotFocus(s, e) {
        calRequiredDate.SetVisible(true);
    }
    function OnClick(s, e) {
        calRequiredDate.SetVisible(false);
    }
    function OnSelectionChanged() {
        var date = calRequiredDate.GetSelectedDate();
        txtRequiredDate.SetText(date.toDateString());
        calRequiredDate.SetVisible(false);
    }
</script>

lunes, 3 de noviembre de 2014

Implementar la funcionalidad de contar los caracteres restantes en un control


Para implementar la funcionalidad de contar los caracteres y limitarlos en un control de Devexpress se puede crear un archivo js para agregar las siguientes funciones:

function RecalculateCharsRemaining(editor) {
    var maxLength = parseInt(editor.maxLength ? editor.maxLength : editor.GetInputElement().maxLength);
    var editValue = editor.GetValue();
    var valueLength = editValue != null ? editValue.toString().length : 0;
    var charsRemaining = maxLength - valueLength;
    SetCharsRemainingValue(editor, charsRemaining >= 0 ? charsRemaining : 0);
}
function SetCharsRemainingValue(textEditor, charsRemaining) {
    var associatedLabel = ASPxClientControl.GetControlCollection().Get(textEditor.name + "_cr");
    var color = GetLabelColor(charsRemaining).toString();
    associatedLabel.SetText("<span style='color: " + color + ";'>" + charsRemaining.toString() + "</span>");
}
function GetLabelColor(charsRemaining) {
    if (charsRemaining < 5) return "red";
    if (charsRemaining < 12) return "#F3A250";
    return "green";
}

// ASPxMemo - MaxLength emulation
function InitMemoMaxLength(memo, maxLength) {
    memo.maxLength = maxLength;
}
function EnableMaxLengthMemoTimer(memo) {
    memo.maxLengthTimerID = window.setInterval(function () {
        var text = memo.GetText();
        if (text.length > memo.maxLength) {
            memo.SetText(text.substr(0, memo.maxLength));
            RecalculateCharsRemaining(memo);
        }
    }, 50);
}
function DisableMaxLengthMemoTimer(memo) {
    if (memo.maxLengthTimerID) {
        window.clearInterval(memo.maxLengthTimerID);
        delete memo.maxLengthTimerID;
    }
}

Agregar la referencia a nuestro archivo js:

 <script src="../Content/functions.js" type="text/javascript"></script>


Luego en el markup, agregar lo siguiente a los eventos del cliente del control:

<ClientSideEvents Init="function(s, e) { InitMemoMaxLength(s, 128); RecalculateCharsRemaining(s); }"                                    GotFocus="EnableMaxLengthMemoTimer" LostFocus="DisableMaxLengthMemoTimer"
KeyDown="RecalculateCharsRemaining" KeyUp="RecalculateCharsRemaining" />

El segundo parámetro en la función InitMemoMaxLength es el máximo de caracteres que  aceptará el control.

Luego podemos agregar  un span con una etiqueta que mostrará el número de caracteres restantes de la siguiente manera:
 <span class="chrm">Characters remaining: <dx:ASPxLabel ID="txtEmail_cr" runat="server" EnableClientSideAPI="True" />     </span>

El ID de la etiqueta que mostrará los caracteres restantes debera tener el mismo nombre que el control a validar mas el sufijo _cr.


martes, 28 de octubre de 2014

Mapear un campo numerico que puede ser nulo a un atributo de un objeto

Cuando tenemos un código como el siguiente:
if (dt.Rows.Count > 0)
     {
      this._holderID = int.Parse(dt.Rows[0]["holder_id"].ToString());
      this._item = int.Parse(dt.Rows[0]["item"].ToString());
      this._holderType = dt.Rows[0]["htype_id"].ToString();
      this._qty = int.Parse(dt.Rows[0]["qty"].ToString());
      this
._prodID =int.Parse(dt.Rows[0]["prod_id"].ToString());
      this._woID =int.Parse(dt.Rows[0]["wo_id"].ToString());
      this._stat = Stat.Loaded;
     }


en el cual tratamos de mapear los campos prod_id y wo_id a las variables _prodID y _woID de un objeto nos provoca un error al tratar de pasar un string vacio a entero en el caso de que ese campo de la tabla este vacío.
La solución es muy simple solo hay que comprobar primero si el campo esta vacío, en ese caso le ponemos un valor por omisión (en este caso 0), y en caso de que el campo no este vacio lo convertimos a entero y lo asignamos a la variable de nuestro objeto:


El codigo resultante quedaría asi:


if (dt.Rows.Count > 0)
     {
      this._holderID = int.Parse(dt.Rows[0]["holder_id"].ToString());
      this._item = int.Parse(dt.Rows[0]["item"].ToString());
      this._holderType = dt.Rows[0]["htype_id"].ToString();
      this._qty = int.Parse(dt.Rows[0]["qty"].ToString());
      this._prodID = dt.Rows[0]["prod_id"].ToString().Trim() == string.Empty ? 0 : int.Parse(dt.Rows[0]["prod_id"].ToString());
      this._woID = dt.Rows[0]["wo_id"].ToString().Trim() == string.Empty ? 0 : int.Parse(dt.Rows[0]["wo_id"].ToString());
      this._stat = Stat.Loaded;

     }



Como podemos observar la solución es simple.
Happy Coding!!!

Metodos para buscar en una lista

Cuando quieran encontrar elementos en una lista de objetos pueden usar ciclos, aunque es mejor utilizar los metodos búsqueda Find, FindAll,  Exists e IndexOf.

Obtener el elemento con Find

En lugar de utilizar un bucle foreach con un if , se puede utilizar el método Find en la lista.  Devuelve el primer objeto encontrado..
using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        List<int> list = new List<int>(new int[] { 19, 23, 29 });

        // Encuentra el primer elemento mayor a 20
        int result = list.Find(item => item > 20);

        Console.WriteLine(result); // 23
    }
}
Descripción. Este código recorre cada valor int en la lista desde el principio y prueba cada valor para ver si es mayor a 20, y devuelve el primer valor encontrado (en este caso el numero 23). 
Un ejemplo mas completo:
Supongamos que tenemos la siguiente clase:
public class Employee{        public String EmpCode;    
    public String FirstName;    
    public String LastName; 
   
    public DateTime DateOfBirth;
    public String Department;
    public String Designation;
    //Constructor
    public Employee(String ecode, String fname, String lname, DateTime dob, String dept, String desg)
    {
         EmpCode = ecode;
         FirstName = fname;
         LastName = lname;
         DateOfBirth = dob;
         Department = dept;
         Designation = desg;    
    }
}
y tenemos una lista de objetos de tipo Employee...
public class EmployeeList : List<Employee>{ }  
en la cual agregamos los siguientes empleados...
EmployeeList elist = new EmployeeList();
elist.Add(new Employee("1","Ruben","Jacome",DateTime.Now,"Ingenieria de Manufactura","Programador"));
elist.Add(new Employee("2","Alejandra","Cruz",DateTime.Now,"Desarrollo de Software","Programador"));
elist.Add(new Employee("3","Mario","Gonzalez",DateTime.Now,"PCL","Supervisor"));
elist.Add(new Employee("4","Bob","Meyer",DateTime.Now,"Divisional","Gerente"));
y ahora buscamos a Bob...
Employee em = elist.Find(delegate(Employee e) { return e.FirstName == "Bob"; });
Ahora tendremos en em el objeto Employee que tenga el FirstName = "Bob".
Nota sobre las búsquedas hacia atras. Para buscar hacia atrás, utilice el método FindLast, que volvería a 29 en el ejemplo anterior. Analizará la lista desde el último elemento hasta el primero.
Buscar por otros métodos. También hay métodos FindIndex y FindLastIndex que se pueden utilizar para regresar el índice de los valores encontrados en la busqueda

Entendiendo FindAll

El método FindAll devuelve una lista de objetos del mismo tipo con todos los elementos que coinciden con la busqueda.

Utilizando Exists

El método Exists devuelve true o false dependiendo de si cualquier elemento coincide con el parámetro de busqueda.
using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        List<int> list = new List<int>();
        list.Add(7);
        list.Add(11);
        list.Add(13);

        // Busca si existen valores mayores a 10
        bool exists = list.Exists(element => element > 10);
        Console.WriteLine(exists); // True

        // Busca por numeros menores a 7
        exists = list.Exists(element => element < 7);
        Console.WriteLine(exists); // False
    }
}
Descripción: En este ejemplo se prueba primero para ver si algun elemento de la lista tiene un valor mayor a 10, el cual regresa true. Despues, prueba por valores menores a 7, los cuales regresan false. 

Usando IndexOf

El método IndexOf tiene dos sobrecargas. Acepta el valor que desee encontrar como primer parámetro y, a continuación, devuelve la ubicación del valor en un arreglo.
using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        List<int> primes = new List<int>(new int[] { 19, 23, 29 });

        int index = primes.IndexOf(23); // Existe en la lista
        Console.WriteLine(index);     // 1

        index = primes.IndexOf(10); // No existe en la lista
        Console.WriteLine(index); // -1
    }
}
NOTA. Cuando se utiliza IndexOf, siempre se debe comprobar -1 o se generara una excepcion. Tenga en cuenta que también puede usar LastIndexOf para realizar la búsqueda en el orden inverso.

Crear codigo HTML desde nuestro archivo de code behind

Algunas veces es necesario crear una salida en codigo HTML con informacion proveniente de nuestra base de datos. En ASP tradicional se tenia que embeber el codigo de la base de datos entre el codigo HTML (entre <%   %>).
En NET esto es mas facil, en el siguiente ejemplo usaremos la clase StringBuilder() para crear la cadena de HTML y con el control Literal lo desplegaremos en nuestra pagina.
  • Primero, arrastramos un control Panel desde nuestra barra de herramientas y le asignamos las propiedades de ID, CssClass, etc.
  • Luego, arrastramos un control Literal de la barra de herramientas y le asignamos la propiedad ID.
En modo de diseño nuestra pagina quedaria asi:

En nuetro code behind mandamos el strem de HTML de la siguiente manera:
//Instanciamos la clase StringBuilder para manipular nuestra cadena
StringBuilder MisArchivos = new StringBuilder();
//Luego construimos nuestra cadena con el metodo Append de la clase
MisArchivos.Append("<a href='" + ResolveUrl(dt.Rows[i][2].ToString())+ "'><img border='0' href='");
MisArchivos.Append(dt.Rows[i][2].ToString());
MisArchivos.Append("' src='" + ResolveUrl("~/images/" + dt.Rows[i][0].ToString()+ "'>"));
MisArchivos.Append(dt.Rows[i][1].ToString());
MisArchivos.Append("</img></a> ");
//Le asignamos la cadena construida con el StrinBuilder a la propiedad Text del control Literal
literal.Text = MisArchivos.ToString();

En este caso el dt es un objeto DataTable que trae las direcciones Url de archivos que hay que desplegar en la pagina.
Con esto se desplegaran los controles HTML dentro del panel de la siguiente manera:

Agregar una columna autonumerica a un DataTable

Para agregar una columna autonumerica a un DataTable es necesario crear un objeto DataTable y un objeto Column que tenga la propiedad AutoIncrement en true y luego mezclarlo con el DataTable que deseamos como en el siguiente ejemplo:

DataTable myDt = new DataTable();
DataColumn dc = new DataColumn();
dc.ColumnName = "#";
dc.DataType = typeof(int);
dc.AutoIncrement = true;
dc.AutoIncrementSeed = 1;
dc.AutoIncrementStep = 1;

BoardCode bc = new BoardCode();
DataTable dt = bc.GetHoldersByBcID(int.Parse(this.TextBox1.Text));

myDt.Columns.Add(dc);

myDt.Merge(dt);

this.GridView1.DataSource = myDt;
this.GridView1.DataBind();



Asi, cuando la despleguemos en un DataGridView se mostrara en la primera columna con un contador de renglones.

formato a un campo de fecha de un gridview

En esta ocación vamos a mostrar como cambiar el formato a un campo de un gridview.
El unico detalle que se presenta es que deben ser agregados los campos uno a uno, es decir debe desactivar el "Auto-generate fields" y en la página cambiar a modo "Source" donde vera el gridview de la siguiente forma.
<asp:BoundField DataField="plan_sdate" DataFormatString="{0}" HeaderText="Date" />
Esto nos daria como resultado el formato "8/20/2008 12:00:00 AM"
Para cambiar el formato a fecha corta solo debe modificar el DataFormatString.
DataFormatString="{0:MM/dd/yyyy}"
Lo cual nos dara como resultado "8/20/2008 "
Nota: Tambien se puede usar para cambiar a otros tipos de formato.
Anexo algunos ejemplos.
Ahora ahondemos un poco más en DataFormatString, las siguientes letras son para formatos numéricos:
C -> Muestra los valores numéricos en formato de moneda.
D -> Muestra los valores numéricos en formato decimal.
E -> Muestra los valores numéricos en formato científico (exponencial).
F -> Muestra los valores numéricos en formato fijo.
G -> Muestra los valores numéricos en formato general.
N -> Muestra los valores numéricos en formato numérico.
X -> Muestra los valores numéricos en formato hexadecimal.

Mover mensajes seleccionados a un personal folder en Oulook 2016

Este es un ejemplo de como mover los mensajes seleccionados a un personal folder (pst) en Outlook 2016 usando VBA. Sub MoveInbox()     Mov...