The Geek Inside

Julio Carlos Sánchez Blog

Archive for the 'DotNet' Category

Como obtener la forma padre de un control en C#

En WinForms no existe una forma directa, o que por lo menos yo conozca de traer todos los controles de algún tipo específico para un pre o post procesamiento.

Así que se tienen que recorrer todos los controles para ir procesando el tipo de control que se necesita.

Para esto se pueden encontrar en la red varios artículos.

Sin embargo, en el proyecto en el que me encuentro colaborando actualmente necesitaba hacer algo similar: Descubrir la Forma a la que pertenece un control.

Estuve buscando algo en la red que me pudiera asistir, pero no encontré nada que me fuera útil.

Así que me dispuse a escribir un método que me ayudara en mi tarea, y este es el resultado:

View CodeCSHARP
1
2
3
4
5
6
7
8
9
10
11
12
private Form DiscoverParentForm(Control control)
{
    Control parent = control.Parent;
    Type controlType = parent.GetType();
 
    if (!controlType.IsSubclassOf(typeof(Form)))
    {
        parent = DiscoverParentForm(parent);
    }
 
    return (Form)parent;
}

Si tiene que llevar a cabo esta tarea, pueden usar este método libremente, buena suerte!!!!!. s

4 comments  |  Related posts

Como convertir un List<TypeA> a un List<TypeB>

En ocasiones nos surge la necesidad de pasar los datos de un List<TypeA> a otro List<> conteniendo un objeto de tipo diferente.

Lo primero que se nos ocurre es:

  • Crear un List<> con el tipo destino.
  • Realizar un foreach sobre el List<> con el tipo fuente.
  • Y por cada uno de los elementos:
    • Convertirlo al tipo destino.
    • Agregarlo a la lista destino

Para ejemplificar esto seguiremos los siguientes pasos:

Creamos la lista fuente y agregamos algunos objetos:

View CodeCSHARP
1
2
3
4
5
List<TipoFuente> listaFuente = new List<TipoFuente>();
 
listaFuente.Add(new TipoFuente(2));
listaFuente.Add(new TipoFuente(5));
listaFuente.Add(new TipoFuente(7));

Implementamos el algoritmo descrito anteriormente:

View CodeCSHARP
7
8
9
10
11
12
List<TipoDestino> listaDestino = new List<TipoDestino>();
 
foreach(TipoFuente f in listaFuente)
{
    listaDestino.Add(new TipoDestino(f.id));
}

Esto seguramente funciona, sin embargo existe una manera más sencilla de hacerlo: Usando el método de la clase List llamado ConverAll.

En seguida muestro un fragmento de como implementar la conversión usando dicho método:

View CodeCSHARP
7
8
9
10
11
12
13
List<ConsParamAlertas> consultas;
listaDestino = ((List< TipoFuente >) listaFuente)
                                            .ConvertAll<TipoDestino>(
                                            delegate(TipoFuente f)
                                            {
                                                return (new TipoDestino(f.id));
                                            });

Espero que este pequeño ejemplo les sirva cuando tengan que Convertir un List<TypeA> a un List<TypeB> ;).

No comments  |  Related posts

Expresiones Regulares en VS2005

Hoy tuve que hacer una search & replace de cierta cadena en el proyecto en el que estoy trabajando actualmente.

La cadena en cuestión es la siguiente .RefreshDataSource(datasource); y la cadena por la que se reemplazaría, seria esta: .DataSource = datasource, el nombre del datasource podía cambiar, así que el search & replace no era tan directa, tendría que emplear una expresión regular :D.

A mi me gusta mucho jugar con expresiones regluares, así que me dije: “adelante”, pues me di a la tarea de escribir la regex y obtuve como resultado:

Cadena a buscar: \.RefreshDataSource\s*\((.*)\);
Reemplazar por: .DataSource = $1;

Cual fué mi sorpesa al ver que si encontraba la cadena, sin embargo al reemplazar fallaba:

Cadena encontrada: grdDatos.RefreshDataSource(datos);
Cadena reemplazada: grdDatos.DataSource = ;

Pensé tal vez me equivoqué y la sintaxis para obtener el grupo de reemplazo se representa así: \1, pues no… no era tampoco así… :(

Dudé de mi habilidad para trabajar con expresiones regulares :’(, y tuve que hacer una oración a San Yahoo y San Google, encontré las siguientes referencias:

En los cuales se explican las diferencias entre las expresiones regulares al usar .Net y en el cuadro de diálogo de search & replace de VS2005, y que existen algo llamado tags que al parecer es un tipo de grupo que se captura y se puede usar en dicho dialogo, sólo que se usan los caracteres: ‘{’ y ‘}’, rodeando la expresión.

Aún no entiendo dos cosas:

  • Porqué no se usan las mismas expresiones regulares en .Net y VS2005?
  • Porque usar un tipo de agrupamiento especial?

En el segundo caso tendré que estudiar más acerca del comportamiento y conveniencias de los tags.

Pues bien, se preguntarán como acaba la historia, y que cadenas usé para llevar a cabo el search & replace:

Cadena a buscar: \.RefreshDataSource\s*\({.*}\);
Reemplazar por: .DataSource = \1;
Cadena encontrada: grdDatos.RefreshDataSource(datos);
Cadena reemplazada: grdDatos.DataSource = datos;

Les recomiendo que si va a usar expresiones regulares en el dialogo search & replace de VS2005, consulten las referencias que menciono arriba, así evitaran alguna frustraciones ;).

No comments  |  Related posts

Como usar predicados para buscar en colecciones

En ciertas ocasiones en las que desarrollamos en C# y usamos colecciones genéricas para contener objetos de cierto tipo, una de las partes que parecen más complicadas es hacer la búsqueda de algún item en específico, pues si echamos un vistazo en la documentación tenemos un método llamado Find sin embargo nos pide un objeto de tipo Predicate.

Mmhh y que son los predicados?, los predicados explicados de una manera sencilla no son más que delegados que evalúan el criterio de búsqueda y regresan un valor booleano.

En base a esto podemos hacer uso del método Find pasándole como parámetro un predicado ó método anónimo.

En seguida mostraré un ejemplo en el que usaré ambos puntos de vista.

Comenzaremos por definir la clase que nos servirá como entidad:

View CodeCSHARP
5
6
7
8
9
10
public class Person
{
    public String name;
    public float height;
    public float weight;
}

Creamos la lista, inicializamos los objetos y los agregamos a la lista:

View CodeCSHARP
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
private static List<Person> persons = new List<Person>();
 
public static void Main(String[] args)
{
    Person person;
    person = new Person();
    person.name = "Julio";
    person.height = 1.65F;
    person.weight = 62.0F;
 
    persons.Add(person);
 
    person = new Person();
    person.name = "Carlos";
    person.height = 1.75F;
    person.weight = 67.0F;
 
    persons.Add(person);

Generamos el método que actuará como predicado de nuestra búsqueda:

View CodeCSHARP
39
40
41
42
private static bool IsInList(Person person)
{
    return (person.name == "Carlos");
}

Y por último usamos dicho predicado:

View CodeCSHARP
33
34
35
36
person = null;
 
person = persons.Find(new Predicate<Person>(IsInList));
Console.WriteLine(person.height);

El resultado que obtendremos es 1.75, que es la estatura de Carlos.

Esta implementación es usando un predicado como método de búsqueda, a continuación les mostraré como usar un método anónimo en lugar del predicado.

Como? simple, modificamos la línea 35 de la clase por esta otra:

View CodeCSHARP
35
person = persons.Find(delegate(Person p){return p.name == "Carlos";});

Listo!!!!!, obtendremos los mismos resultados, así que decidan que método es el que más se ajusta a sus necesidades ;).

A continuación les muestro el listado del programa completo, este programa fué probado tanto en Mono 1.9.1 como en el .Net Framework 2.0, con VS2005.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
using System;
using System.IO;
using System.Collections.Generic;
 
public class Person
{
    public String name;
    public float height;
    public float weight;
}
 
public class PredicateDelegateSpike
{
    private static List<Person> persons = new List<Person>();
 
    public static void Main(String[] args)
    {
        Person person;
        person = new Person();
        person.name = "Julio";
        person.height = 1.65F;
        person.weight = 62.0F;
 
        persons.Add(person);
 
        person = new Person();
        person.name = "Carlos";
        person.height = 1.75F;
        person.weight = 67.0F;
 
        persons.Add(person);
 
        person = null;
 
        person = persons.Find(new Predicate<Person>(IsInList));
        //person = persons.Find(delegate(Person p){return p.name == "Carlos";});
        Console.WriteLine(person.height);
    }
 
    private static bool IsInList(Person person)
    {
        return (person.name == "Carlos");
    }
}

Suerte en sus búsquedas :D.

No comments  |  Related posts

Operación invalida de Cross-thread con WinForms

En el proyecto que estoy participando actualmente, uno de los requerimientos era el de crear algunas pantallas las cuales servirán de monitores.

Estos monitores son alimentados en tiempo real consumiendo desde un tópico y refrescando un grid en el cuál se muestran los mensajes que han llegado.

Todo parecía funcionar de manera adecuada, sin embargo al llegar algún mensaje, en ocasiones enviaba un mensaje de error System.InvalidOperationException: Cross-thread operation not valid.

Esto se debe principalmente a que el Thread que llegaba a actualizar el control no era el Thread que había creado el control es decir: El Thread del UI, y esto no es permitido.

Estuve buscando en la red alguna manera de solucionarlo y me encontré con un artículo en Developer Fusion que habla sobre el tema y nos presenta un work around el cual funciona perfectamente.

1 comment  |  Related posts