Página 2 de 4

Orchard Harvest

Dentro de poco, el 13 y 14 de Junio, se celebrará la Orchard Harvest en Ámsterdam. Es la segunda que se celebra y la primera en europa, en ella estarán los máximos responsables de la comunidad de Orchard y es una gran ocasión para hacer networking y conocer en persona a los miemrbos más destacados de la comunidad de Orchard. Por supuesto, allí estaremos algunos miembros de la comunidad hispana también, si quieres unirte ¡pásate por la lista!

Más información: http://euro2013.orchardharvest.org/

 

Testeando componentes en iOS

Desde que se
anunció Xamarin 2.0 testear nuestras aplicaciones Xamarin.iOS desde Visual
Studio ha sido más fácil que nunca, o al menos, no más difícil que cualquier
otra aplicación que desarrollemos con Visual Studio, esto es: usar nuestras
librerías de testing favoritas, nuestra librería de mocking de preferida y
sobre todo, nuestro runner de siempre.

Por norma general
testeamos el dominio de nuestra aplicación y por esta razón, podemos seguir
usando las herramientas que hemos usado siempre, pero la cosa cambia cuando
desarrollamos librerías inevitablemente acopladas a MonoTouch.dll, como puede
ser por ejemplo, un nuevo control de usuario.

Preparando el entorno

En primer lugar,
no es posible testear este tipo de librerías desde Windows. Solamente es
posible testearlas desde un dispositivo, es decir, nuestro runner se ejecuta
en el dispositivo. Por lo tanto, aunque podamos hacer un build, nuestros tests
en esta ocasión, serán dependientes de OSX.

Por otra parte,
dependeremos de NUnitLite para hacer nuestros Assert. NUnitLite (http://www.nunitlite.org/) es una librería
ligera de testing basada en NUnit. De hecho, si ya conoces NUnit, sabrás
trabajar con NUnitLite porque básicamente, es un subset de NUnit. Si no lo
conoces, es muy parecido a MSTest.

Afortunadamente,
Xamarin nos proporciona un tipo de proyecto que tiene este Target, desde
Xamarin Studio -> Nuestra solución -> Añadir proyecto -> iOS Unit
Tests Project. Y lo único que deberemos hacer es ir creando nuestras clases de
tests y, en tiempo de ejecución, el runner descubrirá nuestros tests.

Testeando:

Crearemos una
clase de test simple con unos cuantos tests para ver el funcionamiento del
runner. De hecho, nuevamente Xamarin Studio nos proporciona una plantilla:

[TestFixture]

                public
class FooTest

                {

                                [Test]

                                public
void Pass ()

                                {

                                                Assert.True
(true);

                                }

 

                                [Test]

                                public
void Fail ()

                                {

                                                Assert.False
(true);

                                }

 

                                [Test]

                                [Ignore
(«another time»)]

                                public
void Ignore ()

                                {

                                                Assert.True
(false);

                                }

                }


Como podéis ver la sintaxis es exactamente la misma que la de NUnit.
Finalmente, ejecutamos nuestro proyecto en el emulador (o nuestro dispositivo)
y podremos ejecutar nuestros tests.


 

 

MvvmCross un framework para dominarlos a todos

[Entrada original publicada en proyecto-mono.org]

mvvmMvvmCross nace de una necesidad, una necesidad de llevar el desarrollo móvil multiplataforma al siguiente nivel. La idea principal de MvvmCross es llevar el patrón MVVM al desarrollo para iOS y Android, manteniendo tu código (Model y ViewModel) en una sola librería y reimplementando la Vista en cada plataforma. Como os decía, hoy voy a hablaros del siguiente nivel en el desarrollo móvil multiplataforma.

 

De dónde venimos y a dónde vamos

MvvmCross es un fork de MonoCross. MonoCross grosso modo es un excelente proyecto, que nos permite utilizar el patrón MVC en nuestras aplicaciones de manera muy similar a cómo desarrollaríamos para ASP.NET MVC, es decir, usando el patrón MVC y un sistema de rutas para comunicarnos con la vista.
Otros proyectos en los que se basa MvvmCross son: MvvmLight, ASP.NET MVC y OpenNetCF.

Por supuesto para poder ejecutar nuestras aplicaciones con diferentes targets, en nuestro caso iOS y Android (además de Windows Phone) necesitaremos MonoTouch y MonoForAndroid. Si esto te parece poco, actualmente hay soporte para OSX, WPF, Windows forms  y Windows RT que aunque no lo veremos aquí, la forma de proceder es análoga.

MVVM Nuestro aliado

Si has desarrollado para desktop o móvil con las tecnologías de Microsoft, seguramente ya conoces el patrón MVVM. Si por el contrario vienes del mundo iOS o Android quizá no te resulta tan familiar, para ellos, lo explico brevemente:

El patrón MVVM (Model View ViewModel) es una variación del patrón MVC (Model View Controller). El modelo y la vista básicamente son los mismos que en  MVC, donde encontramos la diferencia principal es en Controller vs ViewModel. El ViewModel es un mediador entre el modelo y la vista, es el responsable de exponer los datos a la vista para que ésta los muestre a través de comandos (basados en eventos) que la vista puede utilizar para comunicarse con el ViewModel.

Es muy fácil deducir el alto grado de desacoplamiento que tenemos utilizando el patrón arquitectónico MVVM, lo que nos proporciona dos grandes ventajas: Facilidad para realizar UnitTest (muy fácil usar DI + Repository) y sobre todo, facilita construir aplicaciones sin ninguna responsabilidad en la vista más que mostrar datos e interactuar con el usuario.

imgres

Show me the code

Vamos a basarnos en un ejemplo que puedes encontrar en el github del proyecto, en concreto el Sample Tutorial. De esta manera podré centrarme en las partes interesantes y el que quiera investigar por su cuenta, tiene un camino por el que seguir.

Bien, nuestro ViewModel es el siguiente:

 

public class TipViewModel
 
: MvxViewModel
 
{
 
private float _tipValue;
 
public float TipValue
 
{
 
get { return _tipValue; }
 
private set { _tipValue = value; RaisePropertyChanged(() => TipValue); }
 
}
 
private float _total;
 
public float Total
 
{
 
get { return _total; }
 
private set { _total = value; RaisePropertyChanged(() => Total); }
 
}
 
private float _subTotal;
 
public float SubTotal
 
{
 
get { return _subTotal; }
 
set { _subTotal = value; RaisePropertyChanged(() => SubTotal); Recalculate(); }
 
}
 
private int _tipPercent;
 
public int TipPercent
 
{
 
get { return _tipPercent; }
 
set { _tipPercent = value; RaisePropertyChanged(() => TipPercent); Recalculate(); }
 
}
 
public TipViewModel()
 
{
 
SubTotal = 60.0f;
 
TipPercent = 12;
 
Recalculate();
 
}
 
private void Recalculate()
{
 
TipValue = ((int)Math.Round(SubTotal * TipPercent)) / 100.0f;
 
Total = TipValue + SubTotal;
}
}
}

 

Lo primero que destaca es que nuestra clase hereda de MvxViewModel, obligatorio para indicar que se trata de un ViewModel. También tenemos una serie de propiedades que serán las que mostraremos en nuestra vista. Cada propiedad después de cambiar su valor, hace una llamada a RaisePropertyChanged que será el encargado de avisar a la vista de que el valor actual ha cambiado. Por último, en el constructor asignamos unos valores predeterminados y tenemos un método que cambia los valores de algunas de nuestras propiedades.
Además de este ViewModel, tendremos un ViewModel principal desde el que navegaremos hacia este:

 

public class MainMenuViewModel
       : MvxViewModel
   {
       public List Items { get; set; }
 
       public ICommand ShowItemCommand
       {
           get
           {
               return new MvxRelayCommand((type) => DoShowItem(type));
           }
       }
 
       public void DoShowItem(Type itemType)
       {
           this.RequestNavigate(itemType);
       }
 
       public MainMenuViewModel()
       {
           Items = new List()
                       {
                          // typeof(Lessons.SimpleTextPropertyViewModel),
                          // typeof(Lessons.PullToRefreshViewModel),
                           typeof(Lessons.TipViewModel),
                          // typeof(Lessons.CompositeViewModel),
                          // typeof(Lessons.LocationViewModel)
                       };
       }
   }

Como vemos hemos vuelto a heredar de MvxViewModel, ya que volvemos a necesitar un ViewModel. Esta vez tenemos una lista de ítems, del tipo Type que en nuestro caso sólo contendrá un elemento puesto que sólo hemos definido TipViewModel (recomiendo bajarse el proyecto entero para ver los demás tipos), nótese que la lista de ítems podría haber sido perfectamente una lista del tipo ObservableCollection, pero como no va a cambiar no es necesario. También tenemos  un ICommand que ejecutará la acción DoShowItem que, como se puede ver en el código, hace una llamada a RequestNavigate(), con este método le decimos a MvvmCross que queremos ir a otra vista. Esto es maravilloso, nos abstrae del sistema de navegación de la plataforma y de una forma realmente trivial. Por último, en el constructor asignamos la lista de ítems (están comentados todos menos los que usamos en este ejemplo).

CrossPlatform

En el repo podréis ver más plataformas (Android, WinRT y Windows Phone) pero en este ejemplo, por cuestiones de espacio sólo voy a mostrar la de iOS. Y es que iOS tiene un serio inconveniente ya que se suele utilizar para diseñar las interfaces el editor de XCode (aunque yo personalmente prefiero escribir el código). El problema que tiene XCode para diseñar las interfaces es que el XML que genera no es muy agradable a la vista y por tanto no se puede manipular, lo que nos obligará a hacer los bindings en code-behind. Los bindings que haremos con nuestra vista en Windows Phone quedarían en el mismo XAML (de manera muy similar a como trabajaríamos normalmente si somos desarrolladores Windows Phone). En Android, puesto que también se basa en XML para definir la interfaz (y es amigable) el binding también lo podemos introducir como si fueran propiedades de nuestros controles. Pero como he dicho, en iOS no es así y por ello hay que hacer los bindings en code-behind.

Nuestra vista principal:

 

public class MainMenuView
        : MvxBindingTouchTableViewController
    {
        public MainMenuView(MvxShowViewModelRequest request)
            : base(request)
        {
        }
 
        public override void ViewDidLoad()
        {
            base.ViewDidLoad();
 
            Title = "Views";
 
            var tableSource = new TableViewSource(TableView);
            tableSource.SelectionChanged += (sender, args) => ViewModel.DoShowItem((Type)args.AddedItems[0]);
 
            this.AddBindings(
                new Dictionary<object, string>()
                    {
                        { tableSource, "{'ItemsSource':{'Path':'Items'}}" }
                    });
 
            TableView.Source = tableSource;
            TableView.ReloadData();
        }
 
        #region Nested classes for the table
 
        public sealed class TableViewCell
            : MvxBindableTableViewCell
        {
            public const string BindingText = @"{'TitleText':{'Path':'Name'},'DetailText':{'Path':'FullName'}}";
 
            public TableViewCell(UITableViewCellStyle cellStyle, NSString cellIdentifier)
                : base(BindingText, cellStyle, cellIdentifier)
            {
                Accessory = UITableViewCellAccessory.DisclosureIndicator;
            }
        }
 
        public class TableViewSource : MvxBindableTableViewSource
        {
            static readonly NSString CellIdentifier = new NSString("TableViewCell");
 
            public TableViewSource(UITableView tableView)
                : base(tableView)
            {
            }
 
            protected override UITableViewCell GetOrCreateCellFor(UITableView tableView, NSIndexPath indexPath, object item)
            {
                var reuse = tableView.DequeueReusableCell(CellIdentifier);
                if (reuse != null)
                    return reuse;
 
                var toReturn = new TableViewCell(UITableViewCellStyle.Subtitle, CellIdentifier);
                return toReturn;
            }
        }
 
        #endregion
    }

Esta es la vista principal, como vemos hereda de   MvxBindingTouchTableViewController que es una subclase de UITableViewController que nos proporciona el framework e implementa ciertas funcionalidades (como el permitirnos hacer bindings). Para no entrar en demasiadas especificaciones de la plataforma en sí, y mantener el artículo crossPlatform voy a centrarme en explicar, brevemente, lo realmente importante aquí:

Con el método AddBindings, que recibe un diccionario como parámetro, le decimos a MvvmCross sobre qué propiedades queremos hacer bindings:
{ tableSource, “{‘ItemsSource’:{‘Path’:’Items’}}” }

Lo que le está diciendo es, “al objeto tableSource (key,object) busca la propiedad ItemsSource y le asignas la propiedad de nuestro ViewModel, Items.

Esto hará que la tabla genere una celda para cada elemento de Items (uno en nuestro caso y cinco en el ejemplo en el que nos basamos). Para asignar las datos que queremos mostrar en cada celda usamos @”{‘TitleText’:{‘Path’:’Name’},’DetailText’:{‘Path’:’FullName’}}”
que como antes, asigna a cada propiedad de la celda un valor del ViewModel. Nótese que está vez no hace falta especificar explícitamente el target porque lo estamos haciendo sobre la celda, antes lo estamos haciendo sobre la clase de la vista en sí y queríamos hacer binding en el objeto tableSource.

La vista donde se expondrá el otro ViewModel es la que sigue:

 

public partial class TipView : MvxBindingTouchViewController
    {
        public TipView (MvxShowViewModelRequest request) : base (request, "TipView", null)
        {
        }
 
        public override void ViewDidLoad ()
        {
            base.ViewDidLoad ();
 
            this.AddBindings(
                new Dictionary<object, string>()
                    {
                        { TipValueLabel, "{'Text':{'Path':'TipValue'}}" },
                        { TotalLabel, "{'Text':{'Path':'Total'}}" },
                        { TipPercentText, "{'Text':{'Path':'TipPercent','Converter':'Int','Mode':'TwoWay'}}" },
                        { TipPercentSlider, "{'Value':{'Path':'TipPercent','Converter':'IntToFloat','Mode':'TwoWay'}}" },
                        { SubTotalText, "{'Text':{'Path':'SubTotal','Converter':'Float','Mode':'TwoWay'}}" },
                    });
        }
 
        public override void ViewDidUnload ()
        {
            base.ViewDidUnload ();
 
            // Clear any references to subviews of the main view in order to
            // allow the Garbage Collector to collect them sooner.
            //
            // e.g. myOutlet.Dispose (); myOutlet = null;
 
            ReleaseDesignerOutlets ();
        }
 
        public override bool ShouldAutorotateToInterfaceOrientation (UIInterfaceOrientation toInterfaceOrientation)
        {
            // Return true for supported orientations
            return (toInterfaceOrientation != UIInterfaceOrientation.PortraitUpsideDown);
        }
    }

Esta vez heredamos de MvxBindingTouchViewController puesto que esta vez hemos diseñado nuestra vista con XCode (también está soportado MonoTouch.Dialog). Como vemos en el diccionario de bindings, añadimos varias labels y la propiedad que queremos exponer. Seguro que os habéis fijado, pero si no os lo digo yo, en esas propiedades se observan algunos converters. Y es que sí, lógicamente también podemos definir nuestros propios converters, no lo he querido incluir por el tamaño de la entrada. Pero comentar que se crean de manera análoga a como lo haríamos en Silverlight.

 Screen Shot 2013-02-19 at 7.37.14 PM

Más allá de MVVM

Como hemos visto MvvmCross nos permite implementar el patrón MVVM en nuestras aplicaciones. Si bien hay particularidades inherentes a cada plataforma (como que en iOS tenemos que ponerlo en code-behind), el resultado en general es sobresaliente. Pero MvvmCross es más que MVVM, MvvmCross incorpora un contenedor de inyección de dependencias de serie, multitud de librerías (como JSON.NET) y lo que es más importante, nos abstrae del acceso a los sensores de cada plataforma (gps y demás). Tiene un sistema de pluggins que por sí solo daría para varias entradas.

Enlaces interesantes

Proyecto en git

Blog de creador

Lista de enlaces interesantes

Tutorial

Desarrollar con MonoTouch desde Visual Studio

Utilizando librerías de clase portables

 

 

 

 

Consola interactiva de C#

Una de las cosas que más me llama la atención de F# (después de su paradigma) es la consola interactiva que trae, me parece de una utilidad extrema. Bueno, pues el proyecto Roslyn que grosso modo nos permite interactuar con el compilador (extraer información de archivos de código, visualizar el árbol de sintaxis, etc.) incorpora una consola interactiva. Os lo podéis descargar de aquí.

Una vez instalada vamos a View->Other Windows->C# Interactive (Ver->Otras ventanas-> X) o pulsando crtl +w, i la podemos sacar.

Podemos acceder a multitud de ensamblados de .NET, guardar variables, ejecutar scripts. Os dejo un ejemplo para que os hagáis a la idea del potencial de la herramienta:

 

Consola

 

Algunos tips útiles son: con #reset se reinicia el estado del entorno, con #cls se limpia la pantalla y desde el explorador de soluciones->algún proyecto->botón derecho->reset c# interactive from project ¡Podemos referenciar nuestro propio proyecto para probar cosas “on the flight”!
Happy coding!

Desarrollando para iOS desde VisualStudio 2012 con MonoTouch

Hace un tiempo encontré en GitHub una extensión para Visual Studio que si bien no permite ejecutar el emulador de iOS en Visual Studio (básicamente por lo integrado que está Cocoa en OSX), sí que nos permite desarrollar para MonoTouch usando como principal IDE VisualStudio, incluso permite compilar las librerías. Básicamente lo que hace es añadir las referencias de las librerías de MonoTouch por nosotros (podríamos hacerlo manualmente, pero francamente, es un coñazo).
Bien, la extensión en cuestión es esta: https://github.com/ste8/VSMonoTouch. En el enlace tiene las instrucciones para su instalación e información de la misma. Igualmente, aquí hay un enlace con un ejecutable.

 

Imagen

Instrucciones:

Copiar los binarios de MonoTouch desde tu Mac hacia el entorno de Visual Studio. Es decir, lo ficheros de /Developer/MonoTouch/usr/lib/mono/2.1/ de tu Mac a C:Program Files (x86)Reference AssembliesMicrosoftFramework.NETFrameworkv1.0 tu PC. Esto es así porque debemos indicarle a Visual Studio que ahí están los archivos (para que autocomplete, vamos).

Cuando creamos un nuevo proyecto en Visual Studio, este por defecto nos añade una referencia “invisible” a mscorlib.dll, para el correcto funcionamiento de la extensión, debemos sustituir esa referencia por la que utiliza MonoTouch, es decir copiar dicha dll de la solución de MonoTouch y decirle a VisualStudio que debe utiliza la dll de MonoTouch en su lugar.
Según la web del proyecto, con abrir el .csproj y añadir estas líneas debería valer:

<ItemGroup>

<Reference Include="mscorlib" />

<Reference Include="monotouch" />

<Reference Include="System" />

<Reference Include="System.Xml" />

<Reference Include="System.Core" />

</ItemGroup>

A mí particularmente no me funcionó porque me daba un error de duplicidad de referencias (deben ser las instrucciones para VS2010. Lo solucioné incluyendo en el .csproj esta sentencia:

<PropertyGroup Condition=" ‘$(Configuration)|$(Platform)’ == ‘Debug|AnyCPU’ "> <NoStdLib>True</NoStdLib>
</PropertyGroup>

Por último, dado que MonoDevelop aún no soporta proyectos de VS2012, puede que al abrir el proyecto con VS2012 este cambie el .sln y se vuelva incompatible con MonoDevelop. Es tan simple de solucionar como añadir al inicio del proyecto:

Microsoft Visual Studio Solution File, Format Version 11.00
#Visual Studio 2010

Como veis no es demasiado complicado, llevo un mes desarrollando así y os aseguro que vale la pena: la agilidad de VS, resharper, hacer UnitTest con tu runner favorito (el de resharper en mi caso), mantener proyectos con target para WP7&8, W8, Android e iOS desde el mismo IDE con código que sólo cambie la vista… ¿Cómo? Sí, pero de eso ya hablamos otro día.

¡Preprocesador de plantillas Razor!

Los chicos de Xamarin no dejan de sorprender, si el otro día Lluis Sanchez presentó la increíble herramienta XWT, hoy es el turno de Michael Hutchinson presentando el preprocesador de plantillas Razor. Lo he probado, y es una auténtica pasada. En su blog podemos ver una entrada (publicada hace un par de horas) de cómo usarla en un proyecto MonoTouch, y asegurando que sirve para prácticamente cualquier tipo de proyecto. Yo os haré una demostración en un proyecto de Consola.

En primer lugar debemos descargarnos los fuentes de MonoDevelop y compilarlos (hay mucha documentación en la red sobre esto). A continuación, creamos un nuevo proyecto de consola al que llamaremos TemplateRazor. Creamos una Clase, Foo, con el siguiente código:

   1:  namespace TemplateRazor
   2:   
   3:  {
   4:   
   5:  public class Foo
   6:   
   7:  {
   8:   
   9:  public string Salute {
  10:   
  11:  get{return "Hello Razor";}}
  12:   
  13:  }
  14:   
  15:  }
  16:   

Añadimos un nuevo fichero, HelloWorld.cshtml, desde TextTemplating->Preprocessed Razor Template y escribimos:

   1:  @model Foo
   2:   
   3:  <html>
   4:   
   5:  <body>
   6:   
   7:  @Model.Salute;
   8:   
   9:  </body>
  10:   
  11:  </html>



Ya tendríamos nuestra plantilla lista (si os fijáis nos ha creado dos ficheros un .cshtml y .cs). Ahora sólo falta mostrar el contenido en algún navegador, pero por motivos didácticos vamos a ver el código que nos genera en la consola, para ello:

   1:  using System;
   2:   
   3:  namespace TemplateRazor
   4:   
   5:  {
   6:   
   7:  class MainClass
   8:   
   9:  {
  10:   
  11:  public static void Main (string[] args)
  12:   
  13:  {
  14:   
  15:  var template = new HelloWorld(){Model = new Foo()};
  16:   
  17:  Console.WriteLine(template.GenerateString());
  18:   
  19:  }
  20:   
  21:  }
  22:   
  23:  }
  24:   

Y ¡voilá!

PD Podéis encontrar el proyecto de ejemplo en github.

Haciendo un sitio con Orchard multiidioma

Orchard por defecto no soporta multilocalización o multiidioma, lo cual es comprensible porque sigue la máxima de no soportar aquello que no se utilice. Sin embargo, en un país no anglosajón, y más aún en un país dónde el turismo es uno de los principales sectores de nuestra actividad económica, debemos traducir nuestros sitios para intentar llegar a la máxima audiencia.
En realidad no hay ninguna “best practice” para llevar a cabo este proceso con Orchard, no obstante sí que existen unos pasos en común hay que hacer, y esto es instalar una serie de módulos y activar ciertas características:

En Settings>General podemos añadir los idiomas o localizaciones que queremos que estén disponibles.
El módulo Localization : Permite traducir el contenido del sitio. Por defecto, algunos ContentTypes como Page, ya lo implementan, y al instalarlo nos aparece un link que nos permite añadir soporte para las localizaciones a las que hemos dado soporte en las opciones.

Existen más módulos interesantes para ayudarnos con la implementación multiidioma del sitio: CulturePicker, CultureLayer, etc. Aunque como he comentado van en función de lo que queramos hacer.
Si hay algo que no tiene una solución clara, es cómo contemplar los Menús de la página, hay quien opta por crear un menú entero por cada idioma y usar módulos como CultureLayer para mostrar sólo una de esas capas por idioma. En mi caso particular, lo he solucionado convirtiendo el ContentType Custom Link en localizable (añadiendo manualmente el ContentPart Localizable a CustomLink). Y aunque he tenido que introducir los urls a mano, es bajo mi punto de vista, la mejor solución, al menos por ahora.

Coste de las operaciones.

Motivado por la excelente entrada de Eduard Tomàs, El orden de los algoritmos… esa gran O. Hoy os traigo una pequeña tabla que he confeccionado, intentando mantener la simplicidad, de los tipos de datos más comunes y el coste asintótico de las operaciones habituales.

tabla

Grosso modo estas son las colecciones más usadas y sus costes de las implementaciones más comunes (hay más), como vemos depende de la situación. Por ejemplo, ante la duda de una lista ordenada o no ordenada, nos decantaremos por una u otra dependiendo si tenemos que buscar o insertar más.

¡OrchardHispano ha nacido!

Hoy hemos creado la comunidad hispana de Orchard. Como la mayoría sabréis Orchard es un CMS que corre encima de ASP.NET MVC 4 y está apoyado por Microsoft, de hecho, nació en Redmond.  Por ahora sólo somos unos cuantos, pero estoy seguro que pronto se unirá más gente y formaremos una gran comunidad alrededor de este excelente CMS.

Tenemos mucho trabajo por hacer, pero también tenemos mucha ilusión por este nuevo proyecto. Así que ¡únete!

La lista de correo es orchardhispano@googlegroups.com (un grupo de google) y la web www.orchardhispano.com

[MonoTouch. How to.. Usar TableViewController II CustomCell]

En mi última entrada vimos cómo crear un TableViewController para mostrar nuestros datos en forma de lista, y como plantilla para mostrar los datos elegimos la que viene por defecto. Hoy vamos a ver cómo crear nuestra propia plantilla.

Partimos del proyecto que habíamos creado en la serie anterior “ProbandoTableViewController” y lo primero que haremos será añadir una nueva vista a nuestro proyecto. Por tanto, añadimos iPhoneView (que no iPhoneViewController). Y le asignamos el nombre CustomCell. Y lo abrimos con el XCode. Eliminamos la vista, y añadimos en su lugar un TableViewCell. Agregamos una imagen y un texto: clip_image002[4]Nos dirigimos al menú superior,con nuestro TableViewCell seleccionado, que contiene las propiedades de nuestro control y le asignamos el identificador CustomCell y el Class CustomCell:

clip_image006[4]clip_image004[4]

Ahora guardamos y volvemos a XCode. Lo que viene a continuación es algo confuso y es debido a que la versión de XCode cambió (con XCode 3 era mucho más simple). Debemos crear una clase parcial con el mismo nombre que la vista, es decir, dos ficheros uno con el nombre CustomCell.cs y el otro CustomCell.designer.cs. La clase debe heredar de UITableViewCell y además, tener un constructor con el parámetro IntPtr.

El contenido inicial de CustomCell.cs

 

   1:  using System;
   2:   
   3:  using MonoTouch.Foundation;
   4:   
   5:  using MonoTouch.UIKit;
   6:   
   7:  namespace ProbandoTableViewController
   8:   
   9:  {
  10:   
  11:  public partial class CustomCell:UITableViewCell
  12:   
  13:  {
  14:   
  15:  public CustomCell (IntPtr handle): base (handle){}
  16:   
  17:  public CustomCell(){}
  18:   
  19:  }
  20:   
  21:  }

 

El contenido inicial de CuestomCell.designer.cs

using MonoTouch.Foundation;

namespace ProbandoTableViewController

{

[Register("CustomCell")] 

public partial class CustomCell{}

}

Ahora podemos abrir el CustomView.xib con Xcode y añadir los Outlets correspondientes a la imagen y al label como hemos hecho hasta ahora: arrastrando el control, manteniendo pulsado control, hacia el editor código. Los denominamos ImageCell y LabelName, guardamos y de vuelta para MonoDevelop.

Una vez en MonoDevelop nos dirigimos a la clase que acabamos de crear (en el archivo CustomView.cs) y añadimos el método:

public void addDataToCell(UIImage image, string text)

{

this.TextLabel.Text=text;

var imagen =new UIImageView(image);

imagen.Frame = new System.Drawing.RectangleF(ImageCell.Frame.Location,ImageCell.Frame.Size);

this.ImageCell.AddSubview(imagen);

}

Finalmente, nos dirigimos a la clase que creamos en el post anterior, TableSourceMain, y sustituimos el método GetCell por:

   1:  //Retorna el objeto que vamos a mostrar por pantalla. Es decir, cada celda.
   2:   
   3:  public override UITableViewCell GetCell (UITableView tableView, NSIndexPath indexPath)
   4:   
   5:  {
   6:   
   7:  CustomCell cell =(CustomCell) tableView.DequeueReusableCell(this._cellID);
   8:   
   9:  if(cell==null)
  10:   
  11:  cell =(CustomCell)Runtime.GetNSObject(NSBundle.MainBundle.LoadNib("CustomCell",new CustomCell(),null).ValueAt(0));
  12:   
  13:  cell.addDataToCell(UIImage.FromFile("MonoTouch.png"),_datos[indexPath.Row]);
  14:   
  15:  return cell;
  16:   
  17:  }

Hay que añadir una referencia al espacio de nombres MonoTouch.ObjCRuntime.

Ahora podemos compilar y veremos nuestra aplicación.

Nota: Para ajustar el diseño de la celda a nuestro gusto se puede hacer desde XCode configurando las propiedades, de igual modo para ajustar la tabla, sólo que en éste último caso desde el archivo TableViewControllerMain.xib.

« Siguientes entradas Recientes entradas »