When you see this…

image

… it’s because something is going really really wrong.

Anuncios

Diccionario de mapeo bidireccional (doble indexado) en .NET

Moneando con ViewModels se me ha pasado por la mente una idea un poco loca que finalmente no creo que tenga que realizarla, (enlazar ViewModels con modelos). Habría que realizar una sincronización y traducir uno a otro y viceversa.

Manualmente es pesado y un engorro de los buenos.

Se trataría de un mapeador biyectivo que enlace un ViewModel y el Modelo al que corresponde, de manera que dado uno de ellos, se pudiera obtener el otro mediante indexación.

Me he encontrado un enlace bonito en StackOverflow donde incluso está la implementación, por si algún día la requieres en tu mundo de idas de olla con triple hits incluidos.

¡Toma, collons! a ver si algún día te es de utilidad.

http://stackoverflow.com/questions/268321/bidirectional-1-to-1-dictionary-in-c-sharp

Y para alegrarte la vista, aquí está el código en modo suave:

public class BiDictionaryOneToOne<TFirst, TSecond>
    {
        private IDictionary<TFirst, TSecond> firstToSecond = new Dictionary<TFirst, TSecond>();
        private IDictionary<TSecond, TFirst> secondToFirst = new Dictionary<TSecond, TFirst>();

        #region Exception throwing methods

        /// <summary>
        /// Tries to add the pair to the dictionary.
        /// Throws an exception if either element is already in the dictionary
        /// </summary>
        /// <param name="first"></param>
        /// <param name="second"></param>
        public void Add(TFirst first, TSecond second)
        {
            if (firstToSecond.ContainsKey(first) || secondToFirst.ContainsKey(second))
                throw new ArgumentException("Duplicate first or second");

            firstToSecond.Add(first, second);
            secondToFirst.Add(second, first);
        }

        /// <summary>
        /// Find the TSecond corresponding to the TFirst first
        /// Throws an exception if first is not in the dictionary.
        /// </summary>
        /// <param name="first">the key to search for</param>
        /// <returns>the value corresponding to first</returns>
        public TSecond GetByFirst(TFirst first)
        {
            TSecond second;
            if (!firstToSecond.TryGetValue(first, out second))
                throw new ArgumentException("first");

            return second;
        }

        /// <summary>
        /// Find the TFirst corresponing to the Second second.
        /// Throws an exception if second is not in the dictionary.
        /// </summary>
        /// <param name="second">the key to search for</param>
        /// <returns>the value corresponding to second</returns>
        public TFirst GetBySecond(TSecond second)
        {
            TFirst first;
            if (!secondToFirst.TryGetValue(second, out first))
                throw new ArgumentException("second");

            return first;
        }


        /// <summary>
        /// Remove the record containing first.
        /// If first is not in the dictionary, throws an Exception.
        /// </summary>
        /// <param name="first">the key of the record to delete</param>
        public void RemoveByFirst(TFirst first)
        {
            TSecond second;
            if (!firstToSecond.TryGetValue(first, out second))
                throw new ArgumentException("first");

            firstToSecond.Remove(first);
            secondToFirst.Remove(second);
        }

        /// <summary>
        /// Remove the record containing second.
        /// If second is not in the dictionary, throws an Exception.
        /// </summary>
        /// <param name="second">the key of the record to delete</param>
        public void RemoveBySecond(TSecond second)
        {
            TFirst first;
            if (!secondToFirst.TryGetValue(second, out first))
                throw new ArgumentException("second");

            secondToFirst.Remove(second);
            firstToSecond.Remove(first);
        }

        #endregion

        #region Try methods

        /// <summary>
        /// Tries to add the pair to the dictionary.
        /// Returns false if either element is already in the dictionary        
        /// </summary>
        /// <param name="first"></param>
        /// <param name="second"></param>
        /// <returns>true if successfully added, false if either element are already in the dictionary</returns>
        public Boolean TryAdd(TFirst first, TSecond second)
        {
            if (firstToSecond.ContainsKey(first) || secondToFirst.ContainsKey(second))
                return false;

            firstToSecond.Add(first, second);
            secondToFirst.Add(second, first);
            return true;
        }


        /// <summary>
        /// Find the TSecond corresponding to the TFirst first.
        /// Returns false if first is not in the dictionary.
        /// </summary>
        /// <param name="first">the key to search for</param>
        /// <param name="second">the corresponding value</param>
        /// <returns>true if first is in the dictionary, false otherwise</returns>
        public Boolean TryGetByFirst(TFirst first, out TSecond second)
        {
            return firstToSecond.TryGetValue(first, out second);
        }

        /// <summary>
        /// Find the TFirst corresponding to the TSecond second.
        /// Returns false if second is not in the dictionary.
        /// </summary>
        /// <param name="second">the key to search for</param>
        /// <param name="first">the corresponding value</param>
        /// <returns>true if second is in the dictionary, false otherwise</returns>
        public Boolean TryGetBySecond(TSecond second, out TFirst first)
        {
            return secondToFirst.TryGetValue(second, out first);
        }

        /// <summary>
        /// Remove the record containing first, if there is one.
        /// </summary>
        /// <param name="first"></param>
        /// <returns> If first is not in the dictionary, returns false, otherwise true</returns>
        public Boolean TryRemoveByFirst(TFirst first)
        {
            TSecond second;
            if (!firstToSecond.TryGetValue(first, out second))
                return false;

            firstToSecond.Remove(first);
            secondToFirst.Remove(second);
            return true;
        }

        /// <summary>
        /// Remove the record containing second, if there is one.
        /// </summary>
        /// <param name="second"></param>
        /// <returns> If second is not in the dictionary, returns false, otherwise true</returns>
        public Boolean TryRemoveBySecond(TSecond second)
        {
            TFirst first;
            if (!secondToFirst.TryGetValue(second, out first))
                return false;

            secondToFirst.Remove(second);
            firstToSecond.Remove(first);
            return true;
        }

        #endregion

        /// <summary>
        /// The number of pairs stored in the dictionary
        /// </summary>
        public Int32 Count
        {
            get { return firstToSecond.Count; }
        }

        /// <summary>
        /// Removes all items from the dictionary.
        /// </summary>
        public void Clear()
        {
            firstToSecond.Clear();
            secondToFirst.Clear();
        }
    }

Binding a una lista de cadenas

Ay, si es que tenía toda la pinta de que no iba a funcionar y aun así lo intentaste…

Para que recuerdes, mameluco, intentaste enlazar una ListBox a una lista de cadenas que representaban rutas de acceso a ficheros (estilo “C:\bla.txt”, aunque eso de igual, realmente) y en la ItemDataTemplate le metiste un TextBox con Text=”{Binding}”, a secas, pelao y mondao. ¡Sin Path=algo!

Ahora llega WPF y te trae al mundo real: “tío, no flipes, que el Text es TwoWay por defecto está bien, pero que cuando el usuario escriba algo y se intente actualizar la cadena en cuestión, el propio SUJETO del Binding, que es el source, es la propia cadena”. Es decir, que intentas que el sujeto cambie, no una de sus propiedades. Esto tiene todo tipo de implicaciones jodidas que hacen que NO SEA POSIBLE.

De ahí que WPF se queje y te diga que para realizar un enlace TwoWay o OneWayToSource necesitas especificar un Path o un XPath.

¿Cuál es la solución? Envolver la cadena en una clase y hacer un {Binding Path=CadenaEnCuestion}. Así preservamos la instancia sujeto del Binding y lo que modificamos es una de sus propiedades.

¡Todos felices y un success más para la colección!
Aquí dejo constancia, para que no se te olvide, JMN pardillete.

Flashear Nokia Lumia 920

EDICIÓN: Gracias a nuestro amigo Juanito Limaña, aquí están las instrucciones completas.

  1. Descargar el Nokia Suite Care: http://www.mediafire.com/download/yqm3h1jjj6ref7p/Nokia_Care_Suite_PST_5.0_2012.51.4.4.rar
  2. Instalarlo, luego ejecutáis NOKIA SUITE CARE (en el escritorio) y le dais doble click en Product Support Tool for Store 5.0
    En donde pone Sign in to: Seleccionar CareSuite External.
  3. Conectar el Teléfono, y en las pestañas de arriba selección Tool/ Firmware Download
    Se te abre una ventana y en el rectángulo en blanco ponéis este código 059R2R8 click en CHECK ONLINE Y DOWNLOAD
  4. Una vez descargado, Clic en Programming, y clic en RECOVERY
  5. Le das Clic a START, te saldrá un mensaje de error, Desconecta el teléfono (Apágalo) y dale OK
  6. Clic otra vez en START
  7. Verás que te dice que tienes que mantener presionado las teclas el VOLUMEN ABAJO y EL BOTON DE ENCENDIDO
    y sentirás una pequeña Vibración, en ese momento Conecta el USB y le das a START
  8. En la pantalla de tu PC veras un mensaje que dice Rebooting, y luego te saldrá un mensaje le das OK
  9. Y empieza el flasheo y la actualización a AMBER la pantalla de tu tlefono esta de color Rojizo y una barra de progreso de la actualización
    NO TOQUES Y NO HAGAS NADA espera a que termine que como mucho tarde 3 minutos, luego Cuando termine.
  10. Verás en la Pantalla Successful (y ya esta todo listo!) A disfrutar

* Antes de nada Carga al 100% la Batería,
** Esta actualización y flash es limpia osea sin logos de operador.

A disfrutarlo, y gracias por los comentarios, saludos.

Instrucciones antiguas

Flipa, colega. Hoy se me ocurre flashear la actualización Amber (GDR2) y después de un buen rato dándome este error: “Unable to get error message”, me encuentro en un foro alguien al que le pasaba lo mismo. Resulta que:

  1. En el móvil he pulsado los botones [Bajar Volumen] + [POWER] hasta que ha salido el logo de Nokia.
  2. Acto seguido, le he pulsado el botón de Start en el “Product Support Tool For Store”.
  3. Ya no ha salido ningún error y se ha puesto a flashear como un demonio.

Aquí un ejemplo de captura del final de proceso:

Capture

¡La de truqueles que tiene esto de flashear y el miedo que se pasa a veces! Y todo por no esperar a la actualización OTA.

Más información:

  • Código de producto: 059R2R8 
  • Modelo de teléfono: RM-821
  • Variante: RM-821 VAR EU ES CV BLACK (Unbranded)
  • Firmware: 3047.0000.1326.2004_046
  • Archivos de flash: RM821_059R2R8_3047.0000.1326.2004_046

Modelo inusual: Núcleo de la composición contendor/contenido.

¡Saludos, ávidos reventadores de teclados!

Después de consultarlo con algunos krakens de la escena y ser guiado por ellos he decidido ponerme manos a la obra y darle al diseñador de diagramas para ilustrar lo que creo que me han contado. Y parece ser que el núcleo de la composición es esto.

ClassDiagram1

Aunque como mis facultades están a nivel de 2 de Agosto, tullido mentalmente y con hambre de bollos, puede que se me esté escapando la esencia de lo que me han contado (¡que soy muy torpe a veces!).

De esta manera podríamos tener el mismo elemento en varios contenedores, de manera que podríamos escribir el siguiente código:


        public void AddTwoRelationsForTheSameObject()
        {
            var element = new ComposableElement { Name = "Element1"};

            var rel1 = new Emplacement { Left = 0, Top = 0, Target = element };
            var rel2 = new Emplacement { Left = 20, Top = 10, Target = element };

            element.Contents.Add(rel1);
            element.Contents.Add(rel2);
        }

Como podéis ver, los elementos no poseen de forma intrínseca unas coordenadas, sino que la relación (Emplacement) es quien completa esos datos del modelo.

El problema que publiqué ayer podría empezar con algo así, ¿qué os parece? ¿Errado o fetén?

Caso de un modelo inusual: Elementos relacionados con la presentación.

¿Qué pasa, chavales? A pesar de que normalmente no me lee ni el Tato, ayer mantenía una “conversación” por Twitter, dentro de lo puede ser una conversación en Twitter, con @XaviPaper y con @gulnor. Era sobre un modelo un tanto raro que incluye objetos que normalmente estarían representados directamente en la interfaz gráfica de usuario y no en el modelo. En este caso, los elementos gráficos SON EL MODELO. Se presenta, pues, un problema un tanto atípico. Fundamentalmente, las relaciones son de contenedor/contenido y lo primero en lo que he pensado es en un patrón Composite que incluya a la mayoría de elementos del modelo. También es interesante el tema de que la estructura no es un árbol, sino un grafo. Algunos elementos especiales (formularios) pueden tener más de un padre.

Aquí va todo el enunciado con la descripción completa del problema.

ABSTRACTO

En mis ratos en casa estoy construyendo una especie de maquetador de formularios dinámicos. ​​​​El usuario puede añadir elementos a un formulario, arrastrarlos a diferentes posiciones, redimensionarlos y cambiar sus propiedades. Llegado el momento, el usuario decidirá “renderizar” el formulario y donde corresponda, los elementos del formulario que son dinámicos (campos) tomarán un valor “real” formulario de acuerdo con una fuente de datos (sea un XML, una tabla de una base de datos, un archivo CSV…). Esto sería algo similar a lo que hacen los Bindings en XAML.

He estado dándole vueltas al coco para hacer un modelo flexible, elegante y que “hable” por sí mismo.

He probado varias cosas y no me acaban de convencer. O bien es demasiado restrictivo o demasiado permisivo. T​e​n​g​o​ ​u​n​ ​p​a​r​ ​d​e​ ​prototipos actualmente, pero he decidido no seguir adelante porque la implementación y el modelo empiezan a no casar como me gustaría.

El dominio es un documento destinado a la presentación/impresión, con la particularidad de que habrá partes dinámicas que dependerán de una fuente de datos (por ejemplo, un XML, un archivo de texto o una base de datos).

Podéis imaginar que es un PDF que acepta una fuente de datos “externa” y renderiza el contenido dependiendo de la misma. Si dentro del documento existe un campo que hace referencia a un dato llamado “NombreUsuario”, en el proceso de renderizado, el campo tomará el valor de esa variable y en el campo podrá, por ejemplo “Pepito López”.

ESPECIFICACIONES

Un documento está compuesto de páginas. El tamaño de las páginas es un tamaño estático (ancho x alto). El usuario podrá cambiar el tamaño de la página, pero no estará enlazada con datos (al contrario que los campos dinámicos).

Una página (formulario) está compuesta otros elementos que pueden ser:

  1. Formas (rectángulos, líneas, elipses…). No tienen ningún tipo de dinamismo.
  2. Campos dinámicos: textos. Se enlazan a una variable y se reemplaza al renderizarse.
  3. Imágenes dinámicas: Imágenes. De acuerdo a un token (o ruta de acceso) se pone una imagen u otra.​
  4. Textos fijos.
  5. Elementos compuestos.
  6. Tablas
    1. Tablas cuyos elementos son generados dinámicamente: se sabe el número de columnas, pero no el número de filas.
    2. Tablas cuyos elementos (m x n) se conocen, aunque su contenido puede ser variable.
    3. COMPOSICIÓN: Podrán tener imágenes, texto, campos ¡u otras tablas! Es más puro estilo tablas embebidas de Word o HTML
  7. Gráficos estadísticos
    1. El valor de las variables es dinámico
  8. Secciones (COMPOSICIÓN). Es una especie de contenedor cuyo contenido, además de elementos de su mismo tipo, puede contener todos los anteriores.
  9. El tamaño de una sección es el tamaño que ocupen sus elementos hijo.

Todos los elementos tienen ancho y un alto. La manera de indicar la posición que ocuparán en la página es mediante coordenadas absolutas respecto al punto superior izquierdo de su contenedor.

NOTA. Una sección puede estar contenida en varias páginas o en varias secciones. Es decir, si la página 1 y la 2 comparten la misma sección y la modificamos, el cambio se reflejará en ambas páginas. A la hora de componer una sección a base de otras, la restricción será que una sección no podrá contenerse a sí misma, recursivamente.

Los elementos compuestos me vuelven un poco loco, porque son bastante dinámicos. Por ejemplo, en el caso de una tabla, no solamente las filas se generan de acuerdo a la fuente de datos, sino que los elementos de cada columna son dinámicos ​​​y además hay composición (recursivamente una celda de una tabla puede contener una tabla u otro elemento complejo).

También el tema de la composición de elementos, dudo en cómo se podría hacer.

¿Qué opináis, lobos de mar? ¿Es todo tan jodido como parece? ¿Tengo que hacerme un sistema de layout de doble pasada como el de  WPF para solucionar el tema?

Espero que opinéis 😀 ¿Alguna propuesta?

Más adelante trataré de poner algún diagrama de los que he estado haciendo.