none
realizar calculos en datagrid wpf c# RRS feed

  • Pregunta

  • Hola a todos ante todo gracias por leer mi duda.

    Pues estoy tratando de realizar una operacion interna en el datagrid pues tengo estas columnas

    <DataGrid AutoGenerateColumns="False" Height="301" x:Name="dataGrid1" Width="468" ItemsSource="{Binding}" BorderThickness="0" TabIndex="5" EnableColumnVirtualization="True"  CellEditEnding="dataGrid1_CellEditEnding">
                    <DataGrid.Columns>
                        <DataGridTextColumn Header="CANTIDAD" Binding="{Binding Path=Cantidad}" Width="68"/>
                        <DataGridTextColumn Header="D E S C R I P C I Ó N" Binding="{Binding Path=Descripcion}" Width="200"/>
                        <DataGridTextColumn Header="P/UNITARIO" Width="100" Binding="{Binding Path=PUnitario}"/>
                        <DataGridTextColumn Header="VALOR" Width="97" Binding="{Binding Path=Valor}"/>
                    </DataGrid.Columns>
                    <DataGrid.ContextMenu>
                        <ContextMenu>
                            <MenuItem Name="elimi" Header="Eliminar Fila" Click="DeleteItems_Click">
                                <MenuItem.Icon>
                                    <Image Height="20" Width="20" Source="/ControlLibrary;component/Images/Delete.png" />
                                </MenuItem.Icon>
                            </MenuItem>
                        </ContextMenu>
                    </DataGrid.ContextMenu>
                </DataGrid>

     

    y como metodos

    private void dataGrid1_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
            {
                if (dataGrid1.CurrentColumn.Header.ToString() == "P/UNITARIO" || dataGrid1.CurrentColumn.Header.ToString() == "CANTIDAD")
                {
                     Object obs1 = dataGrid1.SelectedItem;
                    DataGridCellInfo cel1 = new DataGridCellInfo(obs1, dataGrid1.Columns[3]);//mover a la 3er fila para poder actualizar el dato
                    dataGrid1.CurrentCell = cel1;
                    dataGrid1.ScrollIntoView(obs1);
                    dataGrid1.BeginEdit();
                }
            }

    tengo una clase donde realizo el calculo

    public class Enumeraciones
        {
            public class Datagris
            {
                public int NoFactura { get; set; }
                public int Cantidad
                {
                    get { return cantida; }
                    set
                    {
                        if (valor != 0)
                            valor = value * puniarios;
                        cantida = value;
                    }
                }
                public string Descripcion { get; set; }
                public double PUnitario
                {
                    get { return puniarios; }
                    set
                    {
                        if (valor != 0)
                            valor = cantida * value;
                        else
                            Valor = cantida * value;
                        puniarios = value;
                    }
                }
                double valor = 0, puniarios; int cantida = 0;
                public double Valor
                {
                    get {return valor;}
                    set
                    {
                        valor=cantida*puniarios;
                    }
                }
            }
        }

    esto me funciona cuando ya estoy editando valores ya sea la cantidad o punitario pero si agrego una nueva fila no  me funciona:(

    lo q realmente deseo hacer esq se haga la multiplicacion de cada cantidad por precio y mostrarlo en el valor

    jueves, 9 de junio de 2011 16:10

Respuestas

  • Hola victor.

    En un principio la idea es esa, pero hay algunos codigos que no estan bien, te comento:

    1.- El evento CellEditing, no se para que esta exactamente,  de modo que se puede quitar.

    2.- Si quieres que se actualice la columna Valor del grid, debes hacer un binding en 2 direcciones, definiendo algo asi:

    <DataGridTextColumn Header="VALOR" Width="97" Binding="{Binding Path=Valor, Mode=TwoWay}"/>
    

    Con esto cuando se modifique el valor de la fuente, automaticamente se actualizara el valor del grid.

    3.- Para que el punto 2 funcione, se debe implementar la interfaz de notificaciones en el modelo, y te quedaria algo asi:

     public class Datagris : System.ComponentModel.INotifyPropertyChanged
        {
          public int NoFactura { get; set; }
          public int Cantidad
          {
            get { return cantida; }
            set
            {
              // guardar cantidad y calcular si es necesario
              cantida = value;
              if (PUnitario != 0) Valor = cantida * PUnitario;
    
              // llamar al evento de propiedad modificada si se quiere TwoWay
              //OnPropertyChanged("Cantidad");
            }
          }
          public string Descripcion { get; set; }
          public double PUnitario
          {
            get { return puniarios; }
            set
            {
              // guardar PUnitario y calcular si es necesario
              puniarios = value;
              if (cantida != 0) Valor = puniarios * Cantidad;
    
              // llamar al evento de propiedad modificada si se quiere TwoWay
              //OnPropertyChanged("PUnitario");
            }
          }
          double valor = 0, puniarios; int cantida = 0;
          public double Valor
          {
            get { return valor; }
            set
            {
              valor = value;
              // llamar al evento de propiedad modificada
              OnPropertyChanged("Valor");
            }
          }
    
          /// <summary>
          /// Evento de la interface para notificar los cambios en las propiedades
          /// </summary>
          public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
    
          
          /// <summary>
          /// Funcion que sera llamada cuando ocurra un cambio de propiedad
          /// </summary>
          /// <param name="_name">Nombre de la propiedad</param>
          protected void OnPropertyChanged(string _name)
          {
            
            System.ComponentModel.PropertyChangedEventHandler handler = PropertyChanged;
    
            // invocar el evento solo en caso de que alguien este suscrito
            if (handler != null) handler(this, new System.ComponentModel.PropertyChangedEventArgs(_name));
          }
    
    Aqui se puede ver que se implementa la interface y el evento para usarla, de modo que cualquier control que se suscriba a este evento, sera notificado al cambiar la propiedad y basicamente, eso es lo que hace la columna cuando le agregas el 'TwoWay' en el binding.
    De modo que cuando cambie el valor de la propiedad, el grid volvera a enlazar esa columna.

    4.- He modificado por encima el codigo de las propiedades por que no le encontraba mucho sentido, no se si es esto lo que quieres hacer o tenias otra idea (compara tu codigo para ver las diferencias)

    Creo que no me dejo nada, pruebalo y cuentas que tal.

     


    Saludos
    David González
    MCP, MCTS
    Visita mi Blog en: http://www.dgzornoza.com/
    • Marcado como respuesta victor_23 miércoles, 6 de julio de 2011 4:54
    jueves, 16 de junio de 2011 17:48

Todas las respuestas

  • ¿Con qué tipo de colección alimentas la grilla?
    Nestor Arturo Fernandez Ricaurte
    jueves, 9 de junio de 2011 18:23
  • utilizo ObservableCollection<ClasesGenericas.Enumeraciones.Datagris> collectiondata = new ObservableCollection<ClasesGenericas.Enumeraciones.Datagris>();

    luego lo enlazo al datagrid.ItemsSource=collectiondata;

    jueves, 9 de junio de 2011 21:40
  • Hola victor.

    En un principio la idea es esa, pero hay algunos codigos que no estan bien, te comento:

    1.- El evento CellEditing, no se para que esta exactamente,  de modo que se puede quitar.

    2.- Si quieres que se actualice la columna Valor del grid, debes hacer un binding en 2 direcciones, definiendo algo asi:

    <DataGridTextColumn Header="VALOR" Width="97" Binding="{Binding Path=Valor, Mode=TwoWay}"/>
    

    Con esto cuando se modifique el valor de la fuente, automaticamente se actualizara el valor del grid.

    3.- Para que el punto 2 funcione, se debe implementar la interfaz de notificaciones en el modelo, y te quedaria algo asi:

     public class Datagris : System.ComponentModel.INotifyPropertyChanged
        {
          public int NoFactura { get; set; }
          public int Cantidad
          {
            get { return cantida; }
            set
            {
              // guardar cantidad y calcular si es necesario
              cantida = value;
              if (PUnitario != 0) Valor = cantida * PUnitario;
    
              // llamar al evento de propiedad modificada si se quiere TwoWay
              //OnPropertyChanged("Cantidad");
            }
          }
          public string Descripcion { get; set; }
          public double PUnitario
          {
            get { return puniarios; }
            set
            {
              // guardar PUnitario y calcular si es necesario
              puniarios = value;
              if (cantida != 0) Valor = puniarios * Cantidad;
    
              // llamar al evento de propiedad modificada si se quiere TwoWay
              //OnPropertyChanged("PUnitario");
            }
          }
          double valor = 0, puniarios; int cantida = 0;
          public double Valor
          {
            get { return valor; }
            set
            {
              valor = value;
              // llamar al evento de propiedad modificada
              OnPropertyChanged("Valor");
            }
          }
    
          /// <summary>
          /// Evento de la interface para notificar los cambios en las propiedades
          /// </summary>
          public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
    
          
          /// <summary>
          /// Funcion que sera llamada cuando ocurra un cambio de propiedad
          /// </summary>
          /// <param name="_name">Nombre de la propiedad</param>
          protected void OnPropertyChanged(string _name)
          {
            
            System.ComponentModel.PropertyChangedEventHandler handler = PropertyChanged;
    
            // invocar el evento solo en caso de que alguien este suscrito
            if (handler != null) handler(this, new System.ComponentModel.PropertyChangedEventArgs(_name));
          }
    
    Aqui se puede ver que se implementa la interface y el evento para usarla, de modo que cualquier control que se suscriba a este evento, sera notificado al cambiar la propiedad y basicamente, eso es lo que hace la columna cuando le agregas el 'TwoWay' en el binding.
    De modo que cuando cambie el valor de la propiedad, el grid volvera a enlazar esa columna.

    4.- He modificado por encima el codigo de las propiedades por que no le encontraba mucho sentido, no se si es esto lo que quieres hacer o tenias otra idea (compara tu codigo para ver las diferencias)

    Creo que no me dejo nada, pruebalo y cuentas que tal.

     


    Saludos
    David González
    MCP, MCTS
    Visita mi Blog en: http://www.dgzornoza.com/
    • Marcado como respuesta victor_23 miércoles, 6 de julio de 2011 4:54
    jueves, 16 de junio de 2011 17:48
  • Hola David. saludes

    pues si exacto asi necesitaba ambas direcciones pudieran ser notificadas pues es en tiempo real que requeria la evaluacion. ahora no se si sea yo pero alguna vez te ha sucedido que haciendo una simple suma de decimales te aparezca en un tipo de formato como redondeo ?? ejemplo

    2.3+ 2.5 = 2.79999999999 asi me aparece ultimadamente cualquier operacion pues visto a esto me tome la libertad de usar la funcion de redondeo a 2 pero tienes idea porq sucede esto?

    miércoles, 6 de julio de 2011 4:57