none
Como mostrar un campo de un objeto complejo en un gridview

    Pregunta

  • Estoy realizando el proyecto de fin de grado y hago uso de entity framework y web Services. Mi problema es que quiero mostrar un objeto complejo que pertenece a otro objeto en un gridview. Es decir, tengo mi dto usuario, con sus propiedades Id,Correo,Nombre,Tipo_Usuario y Sexo. Las propiedades Tipo_Usuario y Sexo esta formadas por sus respectivas propiedades id y descripción. La aplicación esta hecha por capas y en mi capa Negocio hago la función para que me devuelva un lista con todos los datos del usuario. En la capa de presentacion recibo de los web services esa lista, que es mi DataSource  y al mostrar los datos en el GridView me muestra lo siguiente : "Cliente_Escritorio.ServiceReference1.Usuario+Tipo" cuando lo que quiero mostrar es la propiedad descripcion del objeto tipo. Cualquier ayuda de como hacer esto me serviría mucho. Gracias. Si alguien procede a ayudarme le aporto el codigo necesario

    miércoles, 13 de junio de 2018 13:43

Respuestas

Todas las respuestas

  • Hola Ismael,

    no puedes mostrar elementos jerarquicos en gridview, lo que tienes que hacer es construir tu dto para que los valores a mostrar estén todos incluidos allí.  Haría falta ver como construyes tu dto

    miércoles, 13 de junio de 2018 15:22
  • Hola Anibal

    Mi dto es asi 

    public class Usuario
        {
            public int Id { get; set; }
            public string Nombre { get; set; }
            public string Contraseña { get; set; }
            public string Correo { get; set; }
            public Tipo TipoUsuario { get; set; }
            public Genero Sexo{ get; set; }



            public Usuario(string nombre, string contraseña, string correo, Tipo esPremium, Genero sexo)
            {
                Nombre = nombre;
                Contraseña = contraseña;
                Correo = correo;
                TipoUsuario = esPremium;
                Sexo = sexo;
            }

            public class Genero
            {
                public Genero()
                {

                }
                public Genero(int id,string descripcion)
                {
                    Id_Sexo = id;
                    Descripcion = descripcion;
                }
                public int Id_Sexo { get; set; }
                public string Descripcion { get; set; }
            }

            public class Tipo
            {
                public Tipo()
                {

                }
                public Tipo(int id,string descripcion)
                {
                    Id_Tipo_Producto = id;
                    Descripcion = descripcion;
                }
                public int Id_Tipo_Producto { get; set; }
                public string Descripcion { get; set; }
            }
        }

    Entonces los webservices me devuelven un objeto de tipo usuario con esas propiedades y de esas propiedades quiero mostrar la de tipo y de las propiedades de tipo unicamente mostrar en una columna la descripcion.

    Gracias

    miércoles, 13 de junio de 2018 15:36
  • Puedes usar un tipo anonimo para alimentar tu grid si por ejemplo lo que recibes está en una lista haz un select para crear tu nuevo tipo de registro:

    List<Usuario> listaUsuarios= obtener los usuarios....

    var usuariosgrid = listaUsuarios.Select(u=>new {Id=u.Id, Nombre=u.Nombre, Tipo = u.Tipo.Descripcion };

    miGrid.DataSource = usuariosGrid;

    miércoles, 13 de junio de 2018 15:56
  • Me parece que su problema está en otra parte.  Parece que usted está asignando la propiedad TipoUsuario a una columna del GridView.  Como es costumbre, el método ToString() es llamado para representar textualmente el objeto.  Entonces lo más sencillo sería hacer su propio ToString().

    public class TipoUsuario
    {
        ...
    
        public override ToString()
        {
            return $"{Descripcion} (ID {Id}";
        }
    }


    Jose R. MCP
    My GIT Repositories | Mis Repositorios GIT

    miércoles, 13 de junio de 2018 18:33
    Moderador
  • Gracias por vuestra ayuda, pero no consigo solucionarlo. Os dejo el codigo que tengo en la capa de presetacion del form Usuarios, en el metodo OnLoad

    private void Usuarios_Load(object sender, EventArgs e)
            {
                dtgUsuarios.AutoGenerateColumns = false;
                using (ServiceReference1.Service1Client cliente = new ServiceReference1.Service1Client())
                {
                    List<ServiceReference1.Usuario> usuarios = new List<ServiceReference1.Usuario>();
                    usuarios.AddRange(cliente.SeleccionarUsuarios());
                    dtgUsuarios.DataSource = usuarios;

                    BindingSource origenDeEnlace = new BindingSource();
                    origenDeEnlace.DataSource = usuarios;
                }
            }

    jueves, 14 de junio de 2018 7:36
  • ¿Probó la solución de ToString() que le di?

    Jose R. MCP
    My GIT Repositories | Mis Repositorios GIT

    jueves, 14 de junio de 2018 9:28
    Moderador
  • Hola, si, probé pero no lo conseguí

    No encuentro la manera de sacar esto adelante. Empiezo a asumir que no hay manera posible de hacerlo

    lunes, 18 de junio de 2018 10:25
  • Cuando usted dice "gridview", ¿es un GridView de ASP.net o es un DataGridView de Windows Forms?  ¿O es alguna otra cosa?

    Jose R. MCP
    My GIT Repositories | Mis Repositorios GIT

    lunes, 18 de junio de 2018 10:54
    Moderador
  • Es un GridView de Windows Forms
    lunes, 18 de junio de 2018 11:00
  • Asumo que el datagridview tiene predefinidas las columnas y me falta saber que tienes en la propiedad "DataPropertyname" de cada columna lo cual es necesario para poder construir el query. 

                

    lunes, 18 de junio de 2018 11:10
  • Un un proyecto de prueba de Windows Forms, creé las clases Person y Gender para representar personas y el género, y luego agregué el siguiente código al evento Load del formulario:

                dgv.AutoGenerateColumns = true;
                List<Domain.Person> persons = new List<Domain.Person>();
                persons.Add(new Domain.Person()
                {
                    Id = 1,
                    FirstName = "Jessica",
                    LastName = "Alba",
                    Gender = new Domain.Gender()
                    {
                        Id = 1,
                        Name = "Femenino"
                    }
                });
                dgv.DataSource = persons;
    

    Cuando corro la aplicación, veo perfectamente una línea en el DataGridView en la que se lee "WindowsFormsApp1.Domain.Gender" en la celda de la columna Gender.  Es lo que yo esperaba y lo que yo imagino que pasa en su proyecto también.

    Para solucionar esto, invalido el método ToString() de la clase Gender de esta manera:

        public class Gender
        {
            public long Id { get; set; }
            public string Name { get; set; }
    
            public override string ToString()
            {
                return $"{Name} ({Id})";
            }
        }
    

    Con esa única modificación, corro el proyecto de prueba y ahora en vez de leer "WindowsFormsApp1.Domain.Gender" en la celda de la columna Gender, ahora se lee "Femenino (1)".  Lo invito a crear un proyecto Windows Forms de prueba para que lo vea con sus propios ojos.


    Jose R. MCP
    My GIT Repositories | Mis Repositorios GIT

    lunes, 18 de junio de 2018 11:15
    Moderador
  • Tengo el autogeneratecolumns a false, y cada columna tiene en el datapropertyname la parte del datasource que quiero mostrar. Por ejemplo en la columna del Id, el datapropertyname es ID y en el Tipo es TipoUsuario que es el objeto que me devuelve el Webservice. Todos los resultado me los muestra bien salvo el tipo y el sexo, que me devuelve lo siguiente : "Cliente_Escritorio.ServiceReference1.Usuario+Tipo"

    

    lunes, 18 de junio de 2018 11:18
  • Haz la prueba creando una nueva variable y asignandola como fuente al DataGridView y dime si te funciona:

    using (ServiceReference1.Service1Client cliente = new ServiceReference1.Service1Client())
                {
                    List<ServiceReference1.Usuario> usuarios = new List<ServiceReference1.Usuario>();
                    usuarios.AddRange(cliente.SeleccionarUsuarios());

                  var usuariosGrid = usuarios.Select(u=>new {Id=u.Id, Nombre=u.Nombre, Contraseña=u.Contraseña, TipoUsuario = u.Tipo.Descripcion, Sexo=u.Genero.Descripcion});
                    dtgUsuarios.DataSource = usuariosGrid;

                    BindingSource origenDeEnlace = new BindingSource();
                    origenDeEnlace.DataSource = usuariosGrid;
                }

    lunes, 18 de junio de 2018 11:33
  • Gracias Anibal, he probado y no me muestra nada en el GridView, esto está siendo un dolor de cabeza
    lunes, 18 de junio de 2018 12:33
  • Hace un buen rato que le puse la solución y se la marqué como respuesta correcta.  Queda en usted seguir intentando otras cosas, o hacerlo de la forma que le propuse.

    Jose R. MCP
    My GIT Repositories | Mis Repositorios GIT

    lunes, 18 de junio de 2018 12:35
    Moderador
  • Si Jose, estoy probando con ello, no me da tiempo a todo, tengo 2 proyectos a la vez, no le voy a dejar sin respuesta
    lunes, 18 de junio de 2018 12:49
  • Puede ser por que falta ponerle el .ToList()  cambia esta linea:

    var usuariosGrid = usuarios.Select(u=>new {Id=u.Id, Nombre=u.Nombre, Contraseña=u.Contraseña, TipoUsuario = u.Tipo.Descripcion, Sexo=u.Genero.Descripcion}).ToList();

    lunes, 18 de junio de 2018 12:53
  • Vaya, mi problema continua pero desde otro lado.

    En mi form, tengo un boton modificar que me sirve para traerme el objeto entero a un nuevo form y poder modificarlo. Al haber cambiado el datasource tendria que volver a convertir el objeto no ? Para que tenga las 2 propiedades

    lunes, 18 de junio de 2018 13:13
  • El error que me devuelve es el siguiente: 

    System.InvalidCastException: 'No se puede convertir un objeto de tipo '<>f__AnonymousType0`7[System.Int32,System.String,System.String,System.String,System.String,System.String,System.Decimal]' al tipo 'Cliente_Escritorio.ServiceReference1.Producto'.'

    lunes, 18 de junio de 2018 13:18