none
Como obtener el valor de una celda seleccionada en un data grid de wpf RRS feed

  • Pregunta

  • Buenas a todos, Estoy tratando de entender el datagrid del wpf, pero es muy abstracto para mi. Bueno, el problema que tengo es que quiero cargar los registros que tiene mi datagrid en cajas de texto, cada vez que seleccione un registro de la datagrid tiene que cambiar dinamicamente los valores de las cajas de texto.

    Se me ocurrieron estas Soluciones:

    1ra. Es capturar el codigo del registro seleccionado del datagrid y con este ejecutar la busqueda en sql y cargar los valores devueltos a mis cajas de texto.

    2da. Es enlazar las cajas de texto al datagrid, de modo que se carguen los datos del registro a las cajas de texto dinamicamente cada vez que seleccione un registro (En los registros que he cargado en mi datagrid hay un campo de tipo varbinary(50) que lo utilizo para guardar la fotos, pero el datagrid no lo carga la foto).

    3ra. En vista de que al cargar los registro al datagrid a travez de un dataset, no podre hacer la convercion del dato varbinary a Image, estoy añadiendo un control de tipo image junto con mis cajas de texto (fuera del datagrid) y aplico la primera solucion.

     

    Nose, cual de las soluciones sea la mas optima, pero por ahora necesito funcionalidad. Porfavor necesito una ayudita Gracias de antemano

     

    miércoles, 4 de mayo de 2011 21:12

Respuestas

  • Hola Limber.

    Si, de nuevo volvemos a las clases conversoras para realizarlo todo (esxisten alternativas, pero esta es mi favorita por la gran flexibilidad que ofrece).

    Un ejemplo mejor:

    Bueno, no se como enlazas al datagrid el datasource o tabla, pero esta es una forma sencilla:

    dataGrid1.ItemsSource = ((System.ComponentModel.IListSource)table).GetList();
    

    Con esto ya tenemos un datatable con sus registros enlazados al grid.

    ahora en el codigo XAML definimos un grid y en los recursos, la clase conversora que sera utilizada para la imagen:

     <Window.Resources>
        
        <!-- Recurso con la clase conversora de imagenes -->
        <local:BytesToImageConverter x:Key="BytesToImageConverter" />
        
      </Window.Resources>
      
      <Grid>
        
        <!-- Datagrid con los datos -->
        <DataGrid Height="216" Margin="12,12,184,0" x:Name="dataGrid1" VerticalAlignment="Top"
             AutoGenerateColumns="False" >
          <DataGrid.Columns>
            <DataGridTextColumn Binding="{Binding Path=nombre}" Header="nombre" />
            <DataGridTextColumn Binding="{Binding Path=apellidos}" Header="apellidos" />
            <DataGridTextColumn Binding="{Binding Path=telefono}" Header="telefono" />
            <!-- Plantilla para la imagen -->
            <DataGridTemplateColumn Header="foto">
              <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                  <Image Source="{Binding Path=foto, Converter={StaticResource BytesToImageConverter}}"></Image>              
                </DataTemplate>
              </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
            
          </DataGrid.Columns>
        </DataGrid>
    
        <!-- panel con el detalle de una fila de un grid -->
        <StackPanel HorizontalAlignment="Right">
          <TextBox Height="23" x:Name="textBox1" Width="120" Text="{Binding SelectedItem.nombre, ElementName=dataGrid1}" />
          <TextBox Height="23" x:Name="textBox2" Width="120" Text="{Binding SelectedItem.apellidos, ElementName=dataGrid1}" />
          <TextBox Height="23" x:Name="textBox3" Width="120" Text="{Binding SelectedItem.telefono, ElementName=dataGrid1}" />
          <Image Height="23" x:Name="image" Width="120" Source="{Binding SelectedItem.foto, ElementName=dataGrid1}" />
        </StackPanel>
    
      </Grid>
    

     

    Este seria un datagrid y un panel con las celdas de las columnas del grid que se quieran, donde estan los campos de una tabla con las columnas (nombre, apellidos, telefono y una foto en un campo Image de SQL server).

    Se pueden ver como esta enlazada cada columna del datagrid a su columna correspondiente y para la imagen, he dispuesto una celda con una plantilla definiendo una imagen y enlazaremos su fuente (Source).

    En los recursos esta definida la clase conversora que sera usada para enlazar el source de la imagen, donde se pasara de un byte[] a un BitmapImage que se podra establecer como fuente a una imagen.

    Bueno, el codigo .cs con la clase conversora, quedaria algo asi:

     /// <summary>
      /// Clase para realizar una conversion para cargar bytes en imagenes
      /// </summary>
      public class BytesToImageConverter : System.Windows.Data.IValueConverter
      {
        /// <summary>
        /// Funcion que sera llamada a traves del binding que haga uso de este conversor en el codigo xaml para realizar la conversion
        /// </summary>
        /// <param name="value">valor original</param>
        /// <param name="targetType">tipo del dato de origen</param>
        /// <param name="parameter">parametros para pasar al binding</param>
        /// <param name="culture">informacion de la cultura usada</param>
        /// <returns>resultado de la conversion</returns>
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
          // verificar el tipo
          if (value.GetType() != typeof(byte[])) return null;
    
          // obtener el array de bytes
          byte[] data = (byte[])value;
    
          // crear un BitmapImage para establecer como source a una imagen
          // y inicializarlo con los bytes
          BitmapImage bitImg = new BitmapImage();
          bitImg.BeginInit();
          bitImg.StreamSource = new System.IO.MemoryStream(data);
          bitImg.EndInit();
    
          // retornar el BitmapImage
          return bitImg;
        }
    
        /// <summary>
        /// NOTA: Esta funcion no es necesaria
        /// </summary>
        /// <param name="value">valor original</param>
        /// <param name="targetType">tipo del dato de origen</param>
        /// <param name="parameter">parametros a pasar al binding</param>
        /// <param name="culture">informacion de la cultura usada</param>
        /// <returns>resultado de la conversion</returns>
        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
          // no necesario
          throw new NotImplementedException();
        }
      }
    

    Mediante esta clase, estaria todo realizado, ya que es usada en el enlzace a la imagen de grid, y en la funcion convert, se convierte el array de bytes enlazado a la columna imagen en un BitmapImage para establecerlo como fuente, de modo que estaria todo resuelto.

    Ya contaras que tal.

     


    Saludos
    David González
    MCP, MCTS
    Visita mi Blog en: http://www.dgzornoza.com/
    • Marcado como respuesta LimberSoft lunes, 23 de mayo de 2011 12:38
    • Desmarcado como respuesta LimberSoft lunes, 23 de mayo de 2011 19:54
    • Marcado como respuesta LimberSoft viernes, 27 de mayo de 2011 15:57
    lunes, 16 de mayo de 2011 10:18

Todas las respuestas

  • Hola Limber.

    ¿Puedes poner el codigo del datagrid para ver la plantilla?

    ¿como estas enlazando el DataSet al DataGrid?

    La mejor opcion de todas formas, es hacer uso de bindings para enlazar los controles.


    Saludos
    David González
    MCP, MCTS
    Visita mi Blog en: http://www.dgzornoza.com/
    jueves, 5 de mayo de 2011 9:33
  • Grascias, bueno. El codigo xaml de mi data grid es el siguiente:

    <Custom:DataGrid x:Name="dgDocente" Margin="10,10,6,0" Height="199.833" ItemsSource="{Binding}" >
                    <VisualStateManager.CustomVisualStateManager>
                        <VisualStateManager/>
                    </VisualStateManager.CustomVisualStateManager>
    </Custom:DataGrid>

     

    Y para poder cargar los datos a mi datagrid uso la siguiente sentencia en el constructor de mi formulario:

    DocenteBE oDocente = new DocenteBE();
    this.DataContext = oDocente.MostrarDocente().Tables[0];

    Lo que hace objeto oDocente es traer un dataset con los datos del docente.

     

    jueves, 5 de mayo de 2011 13:41
  • Hola Limber.

    Vamos por partes, lo primero parece que es enlazar una fila de un datagrid a unos texBoxes. En este post he comentado como hacerlo mediante el uso de bindings:

    http://social.msdn.microsoft.com/Forums/es-ES/wpfes/thread/14969b2b-9a25-4050-8a4d-f38225db269b

    mira si te sirve y me cuentas.


    Saludos
    David González
    MCP, MCTS
    Visita mi Blog en: http://www.dgzornoza.com/
    jueves, 5 de mayo de 2011 18:23
  • Siento no haber respondido antes debido a unos problemitas de factor tiempo.

    Bueno, El enlace que me diste me sirivio de mucho debido a que funciono como yo esperaba, solo que hay un pequeño detalle sobre la foto, como se supone que la cargare a mi control image.

    Por favor te pido me respondas y muchas gracias de antemano.

    viernes, 13 de mayo de 2011 14:28
  • yo lo solucioné con una cosa tan simple como está:

    <

     

    TextBox FontSize="13" Height="23" Margin="10,34,624,0" Name="txtNombreEmpresa" VerticalAlignment="Top" Text="{Binding SelectedItem.EmpNombre, ElementName=dgvDatosEmpresa}"/>

    En Binding seleccionas la columna que quieres que valla a la caja de texto y el nombre del dataGrid.

    Esto lo repites en cada caja de texto y listo.

    No falla...

     
    • Propuesto como respuesta budurex lunes, 16 de mayo de 2011 9:12
    viernes, 13 de mayo de 2011 14:46
  • Hola Limber.

    Si, de nuevo volvemos a las clases conversoras para realizarlo todo (esxisten alternativas, pero esta es mi favorita por la gran flexibilidad que ofrece).

    Un ejemplo mejor:

    Bueno, no se como enlazas al datagrid el datasource o tabla, pero esta es una forma sencilla:

    dataGrid1.ItemsSource = ((System.ComponentModel.IListSource)table).GetList();
    

    Con esto ya tenemos un datatable con sus registros enlazados al grid.

    ahora en el codigo XAML definimos un grid y en los recursos, la clase conversora que sera utilizada para la imagen:

     <Window.Resources>
        
        <!-- Recurso con la clase conversora de imagenes -->
        <local:BytesToImageConverter x:Key="BytesToImageConverter" />
        
      </Window.Resources>
      
      <Grid>
        
        <!-- Datagrid con los datos -->
        <DataGrid Height="216" Margin="12,12,184,0" x:Name="dataGrid1" VerticalAlignment="Top"
             AutoGenerateColumns="False" >
          <DataGrid.Columns>
            <DataGridTextColumn Binding="{Binding Path=nombre}" Header="nombre" />
            <DataGridTextColumn Binding="{Binding Path=apellidos}" Header="apellidos" />
            <DataGridTextColumn Binding="{Binding Path=telefono}" Header="telefono" />
            <!-- Plantilla para la imagen -->
            <DataGridTemplateColumn Header="foto">
              <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                  <Image Source="{Binding Path=foto, Converter={StaticResource BytesToImageConverter}}"></Image>              
                </DataTemplate>
              </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
            
          </DataGrid.Columns>
        </DataGrid>
    
        <!-- panel con el detalle de una fila de un grid -->
        <StackPanel HorizontalAlignment="Right">
          <TextBox Height="23" x:Name="textBox1" Width="120" Text="{Binding SelectedItem.nombre, ElementName=dataGrid1}" />
          <TextBox Height="23" x:Name="textBox2" Width="120" Text="{Binding SelectedItem.apellidos, ElementName=dataGrid1}" />
          <TextBox Height="23" x:Name="textBox3" Width="120" Text="{Binding SelectedItem.telefono, ElementName=dataGrid1}" />
          <Image Height="23" x:Name="image" Width="120" Source="{Binding SelectedItem.foto, ElementName=dataGrid1}" />
        </StackPanel>
    
      </Grid>
    

     

    Este seria un datagrid y un panel con las celdas de las columnas del grid que se quieran, donde estan los campos de una tabla con las columnas (nombre, apellidos, telefono y una foto en un campo Image de SQL server).

    Se pueden ver como esta enlazada cada columna del datagrid a su columna correspondiente y para la imagen, he dispuesto una celda con una plantilla definiendo una imagen y enlazaremos su fuente (Source).

    En los recursos esta definida la clase conversora que sera usada para enlazar el source de la imagen, donde se pasara de un byte[] a un BitmapImage que se podra establecer como fuente a una imagen.

    Bueno, el codigo .cs con la clase conversora, quedaria algo asi:

     /// <summary>
      /// Clase para realizar una conversion para cargar bytes en imagenes
      /// </summary>
      public class BytesToImageConverter : System.Windows.Data.IValueConverter
      {
        /// <summary>
        /// Funcion que sera llamada a traves del binding que haga uso de este conversor en el codigo xaml para realizar la conversion
        /// </summary>
        /// <param name="value">valor original</param>
        /// <param name="targetType">tipo del dato de origen</param>
        /// <param name="parameter">parametros para pasar al binding</param>
        /// <param name="culture">informacion de la cultura usada</param>
        /// <returns>resultado de la conversion</returns>
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
          // verificar el tipo
          if (value.GetType() != typeof(byte[])) return null;
    
          // obtener el array de bytes
          byte[] data = (byte[])value;
    
          // crear un BitmapImage para establecer como source a una imagen
          // y inicializarlo con los bytes
          BitmapImage bitImg = new BitmapImage();
          bitImg.BeginInit();
          bitImg.StreamSource = new System.IO.MemoryStream(data);
          bitImg.EndInit();
    
          // retornar el BitmapImage
          return bitImg;
        }
    
        /// <summary>
        /// NOTA: Esta funcion no es necesaria
        /// </summary>
        /// <param name="value">valor original</param>
        /// <param name="targetType">tipo del dato de origen</param>
        /// <param name="parameter">parametros a pasar al binding</param>
        /// <param name="culture">informacion de la cultura usada</param>
        /// <returns>resultado de la conversion</returns>
        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
          // no necesario
          throw new NotImplementedException();
        }
      }
    

    Mediante esta clase, estaria todo realizado, ya que es usada en el enlzace a la imagen de grid, y en la funcion convert, se convierte el array de bytes enlazado a la columna imagen en un BitmapImage para establecerlo como fuente, de modo que estaria todo resuelto.

    Ya contaras que tal.

     


    Saludos
    David González
    MCP, MCTS
    Visita mi Blog en: http://www.dgzornoza.com/
    • Marcado como respuesta LimberSoft lunes, 23 de mayo de 2011 12:38
    • Desmarcado como respuesta LimberSoft lunes, 23 de mayo de 2011 19:54
    • Marcado como respuesta LimberSoft viernes, 27 de mayo de 2011 15:57
    lunes, 16 de mayo de 2011 10:18
  • Excelente!!! ahora si funciona, muchas gracias David por tu ayuda, aunque creo que recien inicio mi aventura en wpf y talvez necesite en el futuro mas ayuda.

    Saludos a todos y nuevamente gracias.

    lunes, 23 de mayo de 2011 12:38
  • Pucha que verguenza estar de nuevo en esta situacion, creo que me presipite en la solucion.

    Estimado David, El codigo que me diste de ejemplo me funciono hasta el punto de cargar una imagen al datagrid, es decir ya puedo visualizar las fotos en la grilla, pero en el panel del detalle aun no me funciona el enlace de la imagen con el datagrid.

       <Image Height="23" x:Name="image" Width="120" Source="{Binding SelectedItem.foto, ElementName=dataGrid1}" />

    Lo he intentado de muchas formas este enlace y ninguno me funciono por favor te pido una vez mas tu ayuda. (Al decirte que no funciona el enlace me refiero a que no se visualiza en el panel de detalle la foto seleccionada en el datagrid)

    En cuanto al enlace de los demas controles de tipo texto no tengo ningun problema.

    lunes, 23 de mayo de 2011 20:04
  • Hola Limber.

    Asegurate de que el 'source' es correcto, es sensible a mayusculas y debe coincidir exactamente con el path de la imagen de la plantilla del grid (NO con el nombre de la columna).

    Si en el grid tienes esto:

            <!-- Plantilla para la imagen -->
            <DataGridTemplateColumn Header="foto">
              <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                  <Image Source="{Binding Path=enlace, Converter={StaticResource BytesToImageConverter}}"></Image>              
                </DataTemplate>
              </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
    

    La imagen que tienes que enlazar sera algo asi:

    <Image Height="23" x:Name="image" Width="120" Source="{Binding SelectedItem.enlace, ElementName=dataGrid1}" />
    

    De modo que coincidan las propiedades enlazadas.

    Si sigue sin funcionarte, pon el codigo XAML para echarle un vistazo, ya que el error tiene que estar ahi por ser un enlace implicito de propiedades.

     


    Saludos
    David González
    MCP, MCTS
    Visita mi Blog en: http://www.dgzornoza.com/
    martes, 24 de mayo de 2011 6:41
  • Lo he intentado pero sigue sin funcionarme, pero aqui te va mi codigo del datagrid (Estoy probando el codigo en otro proyecto que ya tiene cargadas muchas imagenes en la Base de Datos):

    <Custom:DataGrid x:Name="dgDocente" Margin="10,10,6,0" Height="199.833"  AutoGenerateColumns="False">

        <Custom:DataGrid.Columns>

               <Custom:DataGridTextColumn Binding="{Binding Path=CodBarras}"Header="Codigo"/>

                      <Custom:DataGridTextColumn Binding="{Binding Path=Titulo}" Header

    ="Titulo"/>

                     <Custom:DataGridTextColumn Binding="{Binding Path=Duracion}" Header

    ="Duracion"/>

                      <Custom:DataGridTemplateColumn Header

    ="Caratula">

                         <Custom:DataGridTemplateColumn.CellTemplate

    >

                           <DataTemplate

    >

                              <Image Name="Fotografia" Source="{Binding Path=Caratula, Converter={StaticResource GuardarImagen}}"></Image

    >

                            </DataTemplate

    >

                       </Custom:DataGridTemplateColumn.CellTemplate

    >

                     </Custom:DataGridTemplateColumn

    >

             </Custom:DataGrid.Columns

    >

     </Custom:DataGrid>

    Debido a que no puedo utilizar el datagrid directamente el expression blend me genero una referencia llamada Custom, mediante la cual recien se me habilita el datagrid. La clase convertora se llama GuardarImagen (Se que no es el nombre indicado para mi clase, pero solo estoy haciendo pruebas por el momento).

    Hasta Aqui me carga sin problemas los datos al datagrid incluyendo la imagen. Pero en el panel de detalles no se enlaza la imagen con el Path del Datagrid, lo extraño en esto es que las cajas de texto se enlazan sin problemas.

    Aqui va el codigo de el enlace de la imagen en el panel de detalles.

    <Image Name="Foto1" Source="{Binding SelectedItem.Caratula, ElementName

    =dgDocente}" />

     He pensado que como estoy seleccionando el Item de la caratula de los datos cargados al datagrid, talvez este todavia no este convertido al tipo imagen y se tendria que hacer algo como esto:

    <Image Name="Foto1" Source="{Binding SelectedItem.Caratula, ElementName=dgDocente, Converter={StaticResource GuardarImagen

    }}" />

     Pero tampoco funciona!!!

    Si te sirve de algo tambien aqui te envio la carga de datos al datagrid:

    dgDocente.ItemsSource = ((System.ComponentModel.IListSource)oDocente.MostrarDocente().Tables[0]).GetList();

    En esto tengo un metodo que se llama MostrarDocente que me devuelve un Dataset con los datos de la tabla que contiene las imagenes.

    Por favor ayudadme en estoy, por que me estoy obsesionando en este problema.

    SALUDOS!!!

    miércoles, 25 de mayo de 2011 13:08
  • Hey, entiendo que quieres obtener los datos que ya pusiste en el dataGrid dentro de los TextBox, obviamente es un tanto abstracto acceder a los datos del DataGrid, pero la verdad no es tán complicado, en realidad es muy sencillo y es precisamente eso lo que nos complica el panorama.

    El DataGrid de Silverlight es un control que aunque no lo parezca es muy completo, la lista de colección ITEMSOURCE es totalmente a Generic, y es susceptible a casi cualquier conversión compatible con el tipo de dato. Mucho bla bla, al grano, para obtener los datos del SelectedItem es simple.

     

    Tienes que tener tu Lista o colección de elementos con la que llenaste el DataGrid, veamos el siguiente ejemplo:

     

    Supongamos que nuestra colección de elementos se basa en el siguiente objeto:

    public class miObjeto

    {

    public int Nro {get;set;}

    public string Nombre {get;set;}

    }

     

    Ahora en el codigo de nuestra página XAML tenemos lo siguiente:

     

    List<miObjeto> ListaDG  //UNA LISTA DE ELEMENTOS TIPO miObjeto que se llenará accesando a Base de datos de alguna forma (la que tu elijas, puede ser domain Service, etc.)

     

    private void LlenarDataGrid()  //Un método donde estableces que el source de tu DataGrid es la lista de objetos (que previamente llenaste).

    {

    miDataGrid.ItemSource=ListaDG;

    }

    //para obtener el valor del SelectedRow, sobrescribimos el método SelectionChanged del DataGrid

    private void miDataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)

    {

    miObjeto SeleccionUsuario = miDataGrid.SelectedItem as miObjeto; //direct cast es posible, xq los elements del DG son GENERICOS

    if(SeleccionUsuario != null)  //Ya tienes tu row completo, con todos los elementos que corresponden...

    {

    TextBox1.Text=SeleccionUsuario.ID.ToString();

    TextBox2.Text=SeleccionUsuario.Nombre;

    }

    .............Otra forma de hacerlo en Silverlight 4 con SP1, y teniendo viva la colección de objetos del DataGrid en una lista, es indizar el elemento mediante el SelectedIndex del DataGrid, sin embargo esto no funcionaba con Silverlight 3.

    • Propuesto como respuesta jrafael83 miércoles, 25 de mayo de 2011 15:15
    miércoles, 25 de mayo de 2011 15:14
  • Hola LimberSoft.

    ¿estas usando WPF no?, ¿Que version del framework estas usando?, ¿el namespace 'custom' a donde apunta?

    En un principio, no parece que haya nada mal, solo que tu defines el datagrid con <custom:datagrid> de modo que no creo que uses el mismo que he usado yo, ya que el ejemplo que yo he puesto es de un datagrid de la biblioteca PresentationFramework en el framework 4.0 si usas el 3.5 es posible que estes usando el de la toolkit.

    En definitiva si no usas el del framework 4.0 es posible que la propiedad 'SelectedItem' no funcione correctamente en el binding. Si me dices que la imagen se muestra en el grid pero no se enlaza en el control imagen tiene que ser algo por el estilo.


    Saludos
    David González
    MCP, MCTS
    Visita mi Blog en: http://www.dgzornoza.com/
    miércoles, 25 de mayo de 2011 19:15
  • Saludos David.

    Estoy utilizando visual studio 2008 y al parecer estoy trabajando con el framework 3.5 sp1.

    La referencia que se hace con el custom es la siguiente:

    xmlns

    :Custom=http://schemas.microsoft.com/wpf/2008/toolkit

    En todo caso voy hacer la prueba instalando el visual studio 2010, espero que no haya confictos con el visual studio 2008.

    y te informare luego como me fue...

    Gracias por tu ayuda he aprendido bastante sobre como tipar los datos a un datagrid.

    miércoles, 25 de mayo de 2011 19:49
  • Hola Limber.

    Si, entonces si que es por lo que suponia, es que en la version 3.5 del framework no existia el control datagrid y para usarlo se tenia que instalar la toolkit de wpf, que es el namespace que has indicado, con lo cual el control datagrid no es el mismo, aunque funciona casi de la misma forma y la migracion de uno a otro no deberia ser ningun problema, solo que algunas propiedades y funcionamiento puede cambiar y una de ellas es el binding que he usado yo.

    Bueno, si tienes posibilidad de actualizarte al 2010 con framework 4 bien, no deberias de tener ningun problema, y si quieres quedarte con tu version me lo comentas y te miro como se tendria que enlazar el datagrid de la toolkit, para ver el problema que tiene.

    (aunque yo optaria por actualizarte, WPF salio con la version 3.5 del framework y este utiliza el CLR 2.0, la version 4 del framework ya hace uso del CLR 4.0 y tiene bastantes cosas interesantes para utilizar)


    Saludos
    David González
    MCP, MCTS
    Visita mi Blog en: http://www.dgzornoza.com/
    jueves, 26 de mayo de 2011 10:04
  • Saludos David:

    Mira que me ha costado mucho trabajo migrar mi proyecto de wpf3 a wpf4 , pero ya lo termine y ahora el primer problema que estoy tropezando es la referencia hacia mi clase conversora

    <Window.Resources>
       
        <!-- Recurso con la clase conversora de imagenes -->
        <local:BytesToImageConverter x:Key="BytesToImageConverter" />
       
      </Window.Resources>

    En mi caso la grilla la tengo en una plantilla UserControl, pero no me reconoce la palabra local asi que hice la siguiente referencia  al usercontrol (la referencia hacia el proyecto que contiene la clase conversora):

    <UserControl x:Class="Capa_de_Presentacion.Supervision.ucDocente"
           xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
           xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
           xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
           xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
          xmlns:local="clr-namespace:Capa_de_Presentacion"
           mc:Ignorable="d" 
          
           d:DesignHeight="660" d:DesignWidth="745">

    Y dentro de los recursos de usercontrol algo asi:

    <UserControl.Resources>
         <local:Bytes_a_Imagen x:Key="Bytes_a_Imagen"></local:Bytes_a_Imagen>
        <ResourceDictionary>
          <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="/Estilos/Botones.xaml">
            </ResourceDictionary>
          </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
        
      </UserControl.Resources>

    Como veras tambien estoy referenciando a mis templates que estoy utilizando, pero el problema esta que cuando lo Genero el proyecto para ver los errores, todos los controles no son reconocidos (al decir controles me refiero a los textbox, buttons, datagrids, etc).

    Pero cuando lo suprimo la referencia añadida, todo vuelve a la normalidad, pero la cosa es hacer uso de la clase conversora. Porfavor te pido una vez mas tu ayuda.

    Atentamente: Limber

     
    jueves, 26 de mayo de 2011 16:15
  • Estimado David:

    Tube que poner en comentario el recurso de mis plantillas, debido a que creo que se genera una confusion (Espero me ayudes a resolverlo debido a que la mayoria de mis controles acceden a esos estilos).

    Lo bueno es que  ahora si puedo cargar los registros a mi datagrid incluyendo la foto, pero me encontre con el problema que tenia en wpf 3.5, porque al querer enlazar el item Foto del datagrid al panel de detalles donde muestro la foto, pues no se enlaza todavia.

    Utilizando wpf 4 el codigo de mi datagrid quedo asi:

     <DataGrid x:Name="dgDocente" Margin="10,10,6,0" Height="199.833" AutoGenerateColumns="False" >
            <DataGrid.Columns>
              <DataGridTextColumn Binding="{Binding Path=Cod_Docente}" Header="CI"/>
              <DataGridTextColumn Binding="{Binding Path=Nombre}" Header="Nombre"/>
              <DataGridTextColumn Binding="{Binding Path=Apellidos}" Header="Apellidos"/>
              <DataGridTemplateColumn Header="Fotografia">
                <DataGridTemplateColumn.CellTemplate>
                  <DataTemplate>
                    <Image Name="Fotografia" Source="{Binding Path=Foto, Converter={StaticResource Bytes_a_Imagen}}"></Image>
                  </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
              </DataGridTemplateColumn>                    
            </DataGrid.Columns>        
          </DataGrid> 

    Y el enlace de la foto de mi panel de detalles quedo asi:

    <Image Name="Foto1" Source="{Binding SelectedItem.Foto, ElementName=dgDocente}" />

    Y pues todavia nada que se enlazan.

    Porfavor revisamelo mi codigo, talvez cometi un error.

    jueves, 26 de mayo de 2011 17:50
  • Saludos David:

    Ya encontre el problema, lo que pasaba era que el control de la foto estaba debajo del marco que diseñe y por eso no se podia visualizar, Me di cuenta cuando desidi empezar de nuevo el diseño y pues ya funciona el enlace.

    Muchas Gracias por la paciencia, tambien comprobe que el enlace de la foto no funciona el el wpf 3.5 y que algunas propiedades que utilizaba, quedan obsoletas en wpf 4

    La ultima ayuda que te pido es la siguiente, como puedo referenciar a la clase conversora y al mismo tiempo a mis templates? El codigo de referencia es como sigue:

     <UserControl.Resources>
         <local:Bytes_a_Imagen x:Key="Bytes_a_Imagen"/>
         <!--<ResourceDictionary>
          <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="/Estilos/Botones.xaml">
            </ResourceDictionary>
            
          </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>-->
      </UserControl.Resources>

    La referencia a mis templates estan en comentario (el texto en negritas), cuando utilizo ambas referencias todos los controles no se reconocen.

    Esperando a tu respuesta me despido.

    Atte: Limber

    jueves, 26 de mayo de 2011 19:09
  • Hola Limber.

    Si, cuando mezclas recursos es obligado ponerle una clave al diccionario de recursos que incluyes, de modo que te bastara con poner un x:key="nombre" en el tag <ResourceDictionary>.


    Saludos
    David González
    MCP, MCTS
    Visita mi Blog en: http://www.dgzornoza.com/
    viernes, 27 de mayo de 2011 16:51
  • Hola David:

    He realizado lo que me dijiste pero sigue saliendo el problema de que muestra el error de que no reconoce a ninguno de mis controles utilizados. El codigo lo hice asi:

    <UserControl.Resources>
         <local:Bytes_a_Imagen x:Key="Bytes_a_Imagen"/>
         <ResourceDictionary x:Key="Diccionario">
          <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="/Estilos/Botones.xaml">
            </ResourceDictionary>
          </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
      </UserControl.Resources>

    Creo que mi aventura por wpf 4 va a ser muy complicada!!!

    A la espera de tu respuesta me despido, no sin agradecerte por toda tu ayuda.

    sábado, 28 de mayo de 2011 1:46
  • Hola Limber.

    Esto tambien es de .net 3.5, lo que pasa es que estas cosas generalmente se añaden solas mediante blend o arrastrando controles y muchas veces no nos fijamos como se quedan (por eso no me gustan los asistentes, te crean codigo y no sabes donde).

    Bien, en  un principio no veo que este mal definido, yo lo he probado con el codigo que has puesto y a funcionado correctamente, asegurate de que la ruta del source sea correcta. y prueba dejar solo el resourceDictionary a ver si te funciona y luego con el <local> solo, si ambos te funcionan por separado, te deberia de funcionar conforme lo tienes.

    De todas formas por si tienes muchos problemas, te puedo dar otra opcion, se trata de declarar el ResourceDictionary en el archivo 'app.xaml', de esta forma estara disponible el recurso botones.xaml para toda la aplicacion (que igual es lo que buscas) en lugar de solo para el control de usuario.

    de modo que puedes dejar solo el tag <local:xxx en los recursos del Usercontrol y en el archivo app.xaml incluir los diccionarios de recursos a nivel de aplicacion:

      <Application.Resources>
    
        <ResourceDictionary>
          <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="MainScene.xaml">
            </ResourceDictionary>
          </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
        
      </Application.Resources>
    

     

    Modificando el source para que apunte a tu arhivo de recursos.

    a ver si te funciona ahora.

     

     


    Saludos
    David González
    MCP, MCTS
    Visita mi Blog en: http://www.dgzornoza.com/
    sábado, 28 de mayo de 2011 9:44
  • Hola David:

    Me diste una mejor solucion para utilizar mis templates, y funciona correctamente.

    Muchas, pero muchas gracias David por toda tu ayuda.

    Sabes me funciona muy bien el enlace de los datos de mi datagrid en el panel de detalles que tengo, solo que cuando cargo una nueva imagen a mi control de imagen pues ocurre que el enlace al datagrid se pierde (Debido a que el source se sobre escribe por el nuevo). Dime como puedo volver a enlazar mi control de imagen al datagrid mediante codigo c sharp.

    La verdad me siento muy inexperto, y me da mucha pena seguir preguntandote. Pero en realidad eres la unica persona que me ha guiado muy bien.

    GRACIAS

    domingo, 29 de mayo de 2011 2:10
  • Hola Limber.

    No entiendo muy bien lo que ocurre.

    ¿modificas los datos del enlace al Datagrid y no te funciona o cuando se pierde el enlace y en que control?

    ¿cuando sobreescribes el source?


    Saludos
    David González
    MCP, MCTS
    Visita mi Blog en: http://www.dgzornoza.com/
    lunes, 30 de mayo de 2011 6:47
  • Bueno David lo explicare por pasos:

    Cuando inicio mi UserControl,  cargo la lista de datos al datagrid y los controles que tengo en el panel de detalle los enlazo al Datagrid incluyendo las imagenes (Hasta aqui todo funciona tal como lo he pensado, que cuando selecciono un item del datagrid estos datos tambien se muestren en los controles de mi panel de detalles).

    Ahora tengo en mi panel de detalles botones que me permiten adicionar y modificar registros. Cuando Adiciono un nuevo registro, tambien es necesario cargar una imagen para ese registro y lo hago atravez de un boton llamado Examinar el cual me permite cargar una nueva imagen al control image. El codigo del boton examinar el es el siguiente:

     string rutaimagen="";
        private void btnExaminar_Click(object sender, RoutedEventArgs e)
        {
          BitmapDecoder bitdecoder;
          OpenFileDialog ofd = new OpenFileDialog();
    
          ofd.Filter = "Imagenes jpg(*.jpg) |*.jpg";
    
          if (ofd.ShowDialog() == true)
          {
    
            using (Stream stream = ofd.OpenFile())
            {
    
              bitdecoder = BitmapDecoder.Create(stream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnLoad);
              Foto1.Source = bitdecoder.Frames[0];
    
            }
            rutaimagen = ofd.FileName;
          }
    
          else
          {
            Foto1.Source = null;
          }
        }

    Es aqui donde el Source de control image (llamado Foto1) se sobreescribe, pues cuando mando la orden de adicion de registros, estos se guardan en mi base de datos y posteriormente actualizo la lista de datos que cargo al Datagrid, de modo que el registro que adicione se vea en el datagrid. Y hasta aqui funciona, inclusive en el datagrid se muestra el nuevo registro que adicione con la foto que le cargue.

    El problema esta que el control image de mi panel de detalles (llamado Foto1), ya no se encuentra enlazado con el datagrid, pues la imagen que he cargado para ese nuevo registro se mantiene estatica (es decir que cada vez que selecciono un item en el datagrid la foto del item seleccionado ya no se muestra en el control image de mi panel de detalles). Es por eso que una vez añadido el registro, pueda volver enlazar mi control image del panel de detalles al datagrid (Pero este codigo lo necesito en C#).

    Otro problema que estoy pasando es que cuando selecciono un item del datagrid que tenga una foto, y este registro se muestra en el panel de detalles (incluyendo la foto). Cuando presiono el boton de modificar capturo todos los datos de los controles que se encuentran en el panel de detalles, pero nose como capturar la imagen cargada en el control image. (En el caso de añadir un nuevo registro lo que hago es guardar la direccion de la imagen que se esta cargando en el control image y esta direccion la envio como parametro a una funcion que realiza la conversion de la imagen seleccionada a un tipo byte[]), Entonces el problema es que como la imagen del control image del panel de detalles a sido cargada a travez de un enlace al datagrid, pues no tengo ninguna direccion de imagen la cual pueda convertir a un tipo byte[]. La pregunta es como capturo la imagen que esta cargada en el control image para convertirla en un tipo byte[].

    Decirte que he implementado la siguiente funcion de conversion de una imagen a un tipo byte[]

     public byte[] Image2Bytes(Image img)
    
      {
    
       string sTemp = Path.GetTempFileName();
    
       FileStream fs = new FileStream(sTemp, FileMode.OpenOrCreate, FileAccess.ReadWrite);
    
       img.Save(fs, System.Drawing.Imaging.ImageFormat.Png);
    
       fs.Position = 0;
    
       //
    
       int imgLength = Convert.ToInt32(fs.Length);
    
       byte[] bytes = new byte[imgLength];
    
       fs.Read(bytes, 0, imgLength);
    
       fs.Close();
    
       return bytes;
    
      }
    
    

    Es por eso que necesito enviarle como parametro la imagen que esta cargada dentro de mi control image del panel de detalles.

    Saludos


    lunes, 30 de mayo de 2011 14:30
  • Saludos

    Lo Una forma mas sencialla de obtener los datos de la cenda seleccionada de un datagrid seria Asi

    Datagrid.SelectedItem(("Columna")

    jueves, 19 de junio de 2014 14:03
  • yo lo solucioné con una cosa tan simple como está:

    <

     

    TextBoxFontSize="13"Height="23"Margin="10,34,624,0"Name="txtNombreEmpresa"VerticalAlignment="Top"Text="{BindingSelectedItem.EmpNombre,ElementName=dgvDatosEmpresa}"/>

    En Binding seleccionas la columna que quieres que valla a la caja de texto y el nombre del dataGrid.

    Esto lo repites en cada caja de texto y listo.

    No falla...

     
    A mi no me funciona, mi datagrid lo lleno desde una consulta sql con linq y el datagrid está con binding
    lunes, 3 de abril de 2017 16:03