[ASP.NET] Juice UI Aires frescos para tus WebForms

wijmo_juice1[1]

Hola que tal? En este post voy a hablar un poco más de JuiceUI un plugin para Webforms que dar nuevos aires a tus formularios, encapsulando funcionalidad de jqueryUI y permitiendonos utilizar de manera sencilla en nuestras páginas.

Los componentes de jqueryUI que se incluyen en Juice son:

  • Accordion
  • Autocomplete
  • Button
  • Datepicker
  • Dialog
  • Draggable
  • Droppable
  • ProgressBar
  • Resizable
  • Selectable
  • Slider
  • Sortable
  • Tabs
  • Position

La url del proyecto es  http://juiceui.com/

Veamos un ejemplo, de inicio a fin utilizando JUICE,  vamos a crear un nuevo sitio web, para esto  voy a utilizar Visual Studio 2010, una vez creado vamos a utilizar el instalador de paquetes NuGet:

image

Escribimos JuiceUI en el buscador para obtener la librería y le damos Install.

image

Luego veremos instaladas las referencias, archivos javascript y css en nuestro proyecto.

image

En el web.config veremos que se agregó al referencia al ensamblado y nos indica cual es el prefijo para la utilización de los controles  en las páginas.

    <pages>

      <controls>

        <add assembly=JuiceUI namespace=Juice tagPrefix=juice />

      </controls>

    </pages>

Ahora voy a incluir en la página de default.aspx un control Juice , el datapicker

<asp:Content ID=”BodyContent” runat=”server” ContentPlaceHolderID=”MainContent”>

<h2>
  Prueba con JUICEUI
</h2>

  <p>

  <asp:ScriptManager ID=”ScriptManager1″ runat=”server”></asp:ScriptManager>

   <asp:TextBox runat=”server” ID=”TextBox1″ />

   <juice:Datepicker ID=”Datepicker1″ runat=”server” MinDate=”-20″ MaxDate=”+1M +10D” TargetControlID=”TextBox1″ />

</p>

</asp:Content>

Vemos el resultado al ejecutar el proyecto:

image

Sigamos viendo algunos controles , como por ejemplo el botón, que funciona algo parecido al de jquerymobile, en donde puedes definir un href y luego decorarlo con css para que tenga la apariencia de un botón, de esta manera puedes hacer lo siguiente

<a href=”http://www.chalalo.cl” id=”link” runat=”server”>
      
Ir a Chalalo.cl</a
>

<Juice:button ID=”Button1″ TargetControlID=”link” runat=”server” />

image

Como te mencionaba existe una buena cantidad de controles, con excelente documentación para llegar y utilizar, muy fáciles de implementar con lo que le puedes dar un nuevo aire a tus formularios, te invito a revisarlos en http://juiceui.com/controls

image

Espero que te sirva!
Nos vemos!!
@chalalo

[ASP.NET] No te pierdas estos videos!

Este tiempo se han presentado grandes novedades por parte del Team ASP.NET, hay muchas nuevas características que harán mucho más simples tus desarrollos, especialmente en lo que es SignalR, ASP.NET Web API y su interacción con el client-side, esta buenísima.

Pero hay más y todo lo puedes revisar en esta excelente colección de videos de la aspConf 2012, recomiendo verlos todos! (si es que tienes tiempo), por que te van a dar una clara visón de como se viene el futuro de ASP.NET

http://channel9.msdn.com/Events/aspConf/aspConf

image

Corto el post, he tenido bastante laburo, espero ponerme al día con varios tutoriales que tengo en mente, como el de SignalR.

Saludos!
G.

[Tip] Como hacer que Windows 8 inicie con el escritorio clásico

Hola, este es un tip que a algunos les puede gustar y a otros no,  en mi caso no me es muy cómodo que aparezca al inicio de Windows 8 la interface metro, quizás cuando tenga un tablet si me va a servir, pero por mientras no la quiero, espero que Microsoft incorpore la opción de elegir con que escritorio partir en la versión final.

Bueno, acá va la forma de hacerlo:

Paso 1 , Crear el archivo SCF

Abrimos el notepad y escribimos los siguientes comandos, luego guardamos el archivo con extensión scf.

[Shell]
Command=2
IconFile=Explorer.exe,3
[Taskbar]
Command=ToggleDesktop

En mi caso lo guarde en mi carpeta de usuario:

image

Paso 2 Crear tarea en el programador de Tareas

Luego vamos a programador de tareas, que esta en el panel de control:

image

O puedes ir más rapido utilizando el buscador de aplicaciones apretando Tecla Windows + W y escribiendo “Administrador de Tareas”. (Creo que hay que arreglar esta diferencia de nombres)

Pinchamos en crear nueva tarea, le asignamos un nombre a la tarea, luego vamos a desencadenadores y por ultimo a Acciones.

image

Ahora en Desencadenadores vamos a pinchar en Nuevo y luego seleccionar al Iniciar la Sesión:

image

Por Ultimo nos vamos a acciones y presionamos sobre Nueva y seleccionamos en acción “iniciar un programa”, luego seleccionamos el script que hicimos en el paso 1:

image

Y Listo, cierras el administrador de tareas, reinicias la sesión y ahora verás el escritorio clásico Smile

Espero que te sirva!
@chalalo.

[Tutorial] WebForms & jQueryUI con Drag & Drop

Hola, hoy veremos un tutorial de como implementar un pequeño sistema en donde vamos a utilizar Drag & Drop con jQueryUI. El escenario es el siguiente, tenemos por un lado la columna de Salas y por otro lado la columna de Pacientes.

DragCam

Los requerimientos son:

  1. Las salas deben obtenerse desde la base de datos
  2. Los pacientes deben obtenerse desde la base de datos
  3. Se debe permitir arrastrar un paciente a una sala y registrar su posicion
  4. Se debe permitir el movimiento de pacientes entre salas
  5. Se debe permitir sacar al paciente desde una sala (arrastrar a la columna de pacientes)
  6. Se debe regitrar todo movimiento del paciente

Con estos requrimientos,, comenzamos a construir nuestra modelo base de datos, el cual es bastante simple y cumple con lo que necesitamos:

image

Para facilitar el manejo de los datos , voy a utilizar LinQtoSQL, para ello vamos a tener el siguiente contexto:

image

Con esto ya tenemos nuestro modelo de datos, veamos ahora los métodos que nos van a permitir obtener la lista de Salas y Pacientes que asociaremos a DataList y Repetears.

EL primer método hace una busqueda de todos los pacientes que estan en “la sala de espera” a esa sala le puse el Id=4, y también llamamos al metodo obtSalasAll, que se obtiene todas las salas (menos la sala 4, es la sala de espera)

Public Sub bindAll()
   DataListPaciente.DataSource = obtPacientesAll(4)      
   DataListPaciente.DataBind()
   DataListSalas.DataSource = obtSalasAll()
   DataListSalas.DataBind()
End Sub


Public Function obtPacientesAll(ByVal sala As Integer) As List(Of PacienteUI)

    Dim contexto As New contextoDataContext

    Dim lista = (From p In contexto.Pacientes Where p.IdSala = sala 
               
Select
IdPaciente = p.IdPaciente, 
                       Nombre = p.NombrePaciente,
                       color = p.Prioridade.ColorPrioridad,
                       IdSala = p.IdSala)

     Dim listaPacienteUI As New List(Of PacienteUI)

     For Each obj In lista

         listaPacienteUI.Add(New PacienteUI() With {.Color = obj.color,
         .NombrePaciente = obj.Nombre, .IdPaciente = obj.IdPaciente,
         .IdSala = obj.IdSala})

     Next

     Return listaPacienteUI

 End Function

 

Public Function obtSalasAll() As List(Of Sala)

    Dim contexto As New contextoDataContext

    Dim lista = (From p In contexto.Salas Order By 
                p.NombreSala
Where
p.IdSala <> 4)

    Return lista.ToList

End Function

Para el mostrar los pacientes dentro de la sala de espera, tengo un objeto definido para ese fin, si quieres podrias mostrar el mismo que entrega el contexto.

Class PacienteUI

   Private _IdPaciente As Integer

   Public Property IdPaciente() As Integer

     Get

       Return _IdPaciente

     End Get

     Set(ByVal value As Integer)

       _IdPaciente = value

     End Set

   End Property

 

   Private _nombre As String

   Public Property NombrePaciente() As String

     Get

       Return _nombre

     End Get

     Set(ByVal value As String)

       _nombre = value

     End Set

   End Property

 

   Private _color As String

   Public Property Color() As String

     Get

       Return _color

     End Get

     Set(ByVal value As String)

       _color = value

     End Set

   End Property

 

   Private _IdSala As Integer

   Public Property IdSala() As Integer

            Get

                Return _IdSala

            End Get

            Set(ByVal value As Integer)

                _IdSala = value

            End Set

        End Property

 

End Class

Para cada cambio de posición, ya sea entre salas y a la sala de espera, vamos a updatear mediante una llamada mediante ajax a un webservice indicando el paciente y la sala. Esta llamada la voy a hacer mediante el registro de la referencia del WebService en el ScriptManager. Luego mediante JavaScript invocaremos al WService.

Este WebService como puedes ver actualiza la posición del paciente y luego inserta en la tabla de moviemientos su nueva Sala, siempre y cuando sea distinta a a que ya tenia asignada. Si bien esto lo vamos a validar tambien en el lado del cliente, es importante hacerlo acá, ya que se podría consumir este servicio desde otra fuente.

El código del WebService:

Imports System.Web

Imports System.Web.Services

Imports System.Web.Services.Protocols

<System.Web.Script.Services.ScriptService()> _

<WebService(Namespace:="http://tempuri.org/")> _

<WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _

<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _

Public Class RegistraMovimientosWS

    Inherits System.Web.Services.WebService

 

<WebMethod()> _

  Public Sub RegistraPosicion(ByVal IdPaciente As Integer,
                             
ByVal IdSala As Integer
)

        Dim contexto As New contextoDataContext

        Dim paciente As New Paciente

        paciente = (From p In contexto.Pacientes Where p.IdPaciente = IdPaciente).Single

        If paciente.IdSala <> IdSala Then

            paciente.IdSala = IdSala

 

            Dim movimiento As New Movimiento

            movimiento.IdPaciente = IdPaciente

            movimiento.IdSala = IdSala

            movimiento.Fecha = Date.Now

 

            contexto.Movimientos.InsertOnSubmit(movimiento)

            contexto.SubmitChanges()

        End If

    End Sub

End Class  

Veamos ahora la estructura de nuestro WebForms, primero la columna de Sala de Espera de Pacientes (Columna derecha).

<form id="form1" runat="server">
    <asp:ScriptManager ID="sm1" runat="server" >
        <Services>
            <asp:ServiceReference InlineScript="false"
                 Path
="~/RegistraMovimientosWS.asmx"
/>
        </Services>
    </asp:ScriptManager>
 

   <asp:Button ID="Button1" style="visibility:hidden" runat="server" Text="Button" />

<asp:UpdatePanel ID="UpdatePanel1" runat="server">

  <ContentTemplate>

    <div>

     <div id="salas">

        <asp:DataList ID="DataListSalas" EnableViewState="false" 
         runat
="server" RepeatColumns
="1"
RepeatDirection="Horizontal">

        <ItemTemplate>

         <div id="<%#Eval("IdSala")%>" class="block" 
         
style="background-color: #<%#Eval("ColorSala")%>
">

        <div style="text-align: center; font-size: 18px; border: solid 1px">

<%#Eval("NombreSala")%></div>

        <asp:HiddenField ID="hidsala" runat="server"
       
Value=’<%# eval("IdSala") %>
/>

         <asp:Repeater ID="DataListPacientesSalas" runat="server"
         
 EnableViewState
="false">

              <ItemTemplate>

                <div class="pacienteEnSala arrastra"
               
 sala="<%#Eval("IdSala")%>" id="<%#Eval("IdPaciente")%>
">

                 <%#Eval("NombrePaciente")%></div>

               </ItemTemplate>

           </asp:Repeater>

         </div>

        </ItemTemplate>

     </asp:DataList>

     </div>

    

   <div id="pacientes">

      <asp:DataList ID="DataListPaciente" runat="server"
          
RepeatColumns="3" RepeatDirection
="Vertical">

       <ItemTemplate>

            <div id="<%#Eval("IdPaciente")%>" 
            
sala="<%#Eval("IdSala")%>" 
            
class="blockPaciente arrastra" 
            
style="background-color: #<%#Eval("Color")%>
">

        <div style="text-align: center; font-size: 18px; border: solid 1px;">
 
   <%#Eval("NombrePaciente")%></div>

     </ItemTemplate>

    </asp:DataList>

   </div>

</div>

</ContentTemplate>

<Triggers>

       <asp:AsyncPostBackTrigger ControlID="Button1"  EventName="Click" />

  </Triggers>

</asp:UpdatePanel>

</form>

En vista de diseño veríamos algo así:

image

Puedes notar también que existe un boton que está oculto mediante un estilo, este servirá para generar un postback asincrono para recargar los datos que tienen los elementos datalist  y repeaters.

Veamos el código  que va a dar soporte a la funcionalidad

Primero que nada, vamos a incluir las librerias jQuery y JqueryUI en nuestro proyecto

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js" type="text/javascript"></script>

<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/jquery-ui.min.js"type="text/javascript"></script>

Luego vamos a definir la funcionalidad de Drag & Drop mediante el plugin de JqueryUI. Debemos definir cual es el estilo que será seleccionado para atachar el comportamiento de arrastrar (draggable), en mi caso el estilo arrastra,lo mismo ocurre con droppable, en donde definimos la funcionalidad a realizar cuando se hace el drop:

  • Obtenemos el Id del objeto arrastrable, que corresponde al IdPaciente
  • Obtenemos el Id del objeto que acepta al elemento arrastrable, es decir la sala.
  • Obtenemos el Id de la sala que ya tiene asociado el IdPaciente, esto es importante para no hacer la llamada asincrona cuando movemos el objeto dentro del mismo contenedor.
  • Removemos la clase para mostrar un elemento más pequeño dentro de la sala.
  • LLamamos al Webservice mediante Microsoft Ajax (Recuerda que ya lo registramos en el ScriptManager)
  • Hacemos un PostBack Asíncrono para refrescar los webcontrols.

Lo mismo se hace con el la columna de pacientes, el concepto del Drop de jQueryUI es que definas el selector del objecto que va a ser draggable y el objeto que será droppable y cual es el objeto que acepta: “arrastra”, entonces, así por ejemplo el estilo Block acepta que se arrastren dentro de él objetos “arrastra”.

En la columna pacientes, la sala de espera es la Sala 4, esto se puede mejorar en el código (en eso estoy pero queria postear rápido este ejemplo).

<script type="text/javascript">

 

    window.Error = function(msg) {

        alert(msg);

    }

 

    function UpdPanelUpdate() {

       __doPostBack("<%= Button1.ClientID %>", "");

    }

 

    function creaComportamiento() {

        $(".arrastra").draggable({ revert: ‘invalid’ });

        $(".block").droppable({

            accept: ‘.arrastra’,

            activeClass: ‘droppable-active’,

            hoverClass: ‘droppable-hover’,

            drop: function(event, ui) {

                var idPaciente = parseInt($(ui.draggable).attr(‘id’));

                var idSala = $(this).attr(‘id’);

                var idSalaAnterior = $(ui.draggable).attr(‘sala’);

                if (idSala != idSalaAnterior) {

                    $(ui.draggable).removeClass("blockPaciente");

                    RegistraMovimientosWS.RegistraPosicion(idPaciente,
                                                           idSala);

                    UpdPanelUpdate();

                }

               

            }

        });

        $("#pacientes").droppable({

            accept: ‘.arrastra’,

            drop: function(event, ui) {

                $(ui.draggable).addClass("blockPaciente");

                var idSalaAnterior = $(ui.draggable).attr(‘sala’);

                if (4 != idSalaAnterior) {

                    var idPaciente = parseInt($(ui.draggable).attr(‘id’));

                    RegistraMovimientosWS.RegistraPosicion(idPaciente, 4);

                    UpdPanelUpdate();

                }

            }

        });

    }

   

    $(document).ready(function() {

        creaComportamiento();

    });

 

</script>

Ya habrás notado que todo el comportamiento está encapsulado en “crearComportamiento”, esto tiene una razón de ser, y es que cada vez que el updatePanel hace un post asíncrono , vuelve a crear los objetos del DOM , y no se vuelve a ejecutar el $(document).ready lo que conlleva que este código como está solo se ejecuta la primera vez, una vez hecho el postback deja de funcionar, debido a que no existe nuevamente el bind del comportamiento que proporciona jqueryui a los componentes.   La solución es sencilla, y es que cada vez que llamamos al UpdPanelUpdate() en donde ocupamos como trigger un postback con el botón oculto, llamamos a un método que hace el bindAll y luego llama a “crearComportamiento” mediante el ScriptManager.RegisterStartupScript, con esto nos aseguramos que siempre se vuelva a cargar la funcionalidad despues de los refresh del UpdaPanel.

Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click

   bindAll()

   ScriptManager.RegisterStartupScript(Me, Me.GetType, "script",
                                     
"creaComportamiento();", True
)

 End Sub

Y listo! tenemos la funcionalidad que deaseamos cubriendo las necesidades de los requerimientos que planteamos al principio Smile

Descarga el ejemplo completo con los CSS utilizados acá:
https://www.dropbox.com/sh/75za68riilzehhc/Nk4AV_KPUU/PruebaSinet.zip

Espero que te sea útil, nos vemos!
@chalalo

ASP.NET 4.0 Mejoras en el ScriptManager : ScriptResourceDefinition y AjaxFrameworkMode

Hola que tal? quiero compartir una nueva característica del ScriptManager, que nos va a facilitar la selección y filtro de los scriopt que deseamos incluir en nuestra página, primero que nada veamos el ScriptResourceDefinition, el cual define la ubicación de un recurso script, permitiendo especificar, ruta en modo debug, ruta en modo CDN, combinación de ambos y soporte SSL

La lista de propiedades puedes revisarla acá:
http://msdn.microsoft.com/es-es/library/system.web.ui.scriptresourcedefinition.aspx

image

Veamos un ejemplo práctico, vamos a incluir la librería más conocida y querida por nosotros, obviamente, jQuery. Para esto vamos al Global.asax y escribimos en el método Application_Star el siguiente código (la línea del BundleConfig ya viene en el visual studio 2012)

void Application_Start(object sender, EventArgs e)

{

// Code that runs on application startup

  BundleConfig.RegisterBundles(BundleTable.Bundles);

  ScriptManager.ScriptResourceMapping.AddDefinition(“jquery”, new  
               ScriptResourceDefinition

  {

    Path = “~/scripts/jquery-1.6.2.min.js”,

    DebugPath = “~/scripts/jquery-1.6.2.js”,

    CdnPath = “http://ajax.microsoft.com/ajax/jQuery/jquery-1.6.2.min.js”,

    CdnDebugPath = “http://ajax.microsoft.com/ajax/jQuery/jquery-1.6.2.js”,

    CdnSupportsSecureConnection =true

    });

}

Como se puede apreciar estamos mapeando a un nuevo recurso llamado “jquery”, en donde especificamos la ruta a nivel local para modo release(path) y modo debug, pero tambien si queremos utilizar un CDN de la misma manera, CdnPath para modo release y CdnDebugPath para modo debug, ademas indicamos que se permiten conexiones seguras.

Ahora debemos configurar el ScriptManager en el código declarativo:

<asp:ScriptManager runat=”server” EnableCdn=”false” AjaxFrameworkMode=”Enabled”>
   <Scripts>
       <asp:ScriptReference Name=”jquery” />
   </Scripts>
</asp:ScriptManager>

Acá ya se introduce tambien la nueva característica AjaxFrameworkMode que añade dos nuevos modos de comportamiento del ScriptManager. Enabled , el cual es el valor predeterminado y tiene el mismo comportamiento que versiones anteriores, Explicit, no incluye todos los script, pero asume que se utilizará el Microsoft Ajax, Disabled que no incluye las secuencias de comandos por defecto y asume  que  Microsot Ajax no será utilizado, es decir, no va a cargar ninguna script por defecto.

Si ejecutamos el ejemplo podemos ver los script que se están cargando:

image

Podemos apreciar que estamos cargando la librería jquery y el Microsoft Ajax.

Ahora voy a probar con las siguientes opciones ScriptMode en Release y AjaxFrameworkMode en Disabled

<asp:ScriptManager runat=”server” ScriptMode=”Release” EnableCdn=”false” AjaxFrameworkMode=”Disabled”>
       <Scripts>
           <asp:ScriptReference Name=”jquery” />
       </Scripts>
   </asp:ScriptManager>

image

En este caso solo estamos cargando la libería jquery minimizada ya que es lo que especificamos para modo release.

Y por ultimo, si queremos cargar la librería mediante un CDN solo especificamos true en EnableCDN:

image

Y vemos que efectivamente lo está cargando desde ajax.microsoft.com.
Bastante útiles las nuevas mejoras Smile

Saludos!
@chalalo