none
Problema con el formato de un campo Time de sql server

    Pregunta

  • Un saludo.

    Estoy desarrollando una aplicación con VS 2005. La BD está en un servidor con sql server 2008.

    En un formulario que accede a datos de una tabla en la que he separado los campos de fechas en uno de fecha (date) y otro de hora (time(7)), no tengo forma de que un datagridview represente correctamente el campo de fecha. Por más que indico en su propiedad format HH:mm, siempre me aparecen los segundos.

    La cosa no queda ahí, ya que tengo también un control personalizado que se comporta de la misma manera, o sea, siempre que el bindingsource provoca el evento bindingcomplete, tanto el dgview como mi control presentan el dato con formato HH:mm:ss.

    ¿Alguien sabe a qué se debe y cómo solucionarlo?

    Gracias anticipadas.


    Miguel Ángel Muñoz
    lunes, 03 de octubre de 2011 6:26

Respuestas

  • Prueba reemplazando la class TimeSpanFormatter por esta nueva.

     

    Class TimeSpanFormatter
        Implements IFormatProvider, ICustomFormatter
    
        Private _formatParse As Regex
        Private _timeSpan As TimeSpan
    
        Sub New()
            _formatParse = New Regex("d{1,2}|h{1,2}|m{1,2}|s{1,2}|f{1,7}", RegexOptions.Compiled)
        End Sub
        Public Function GetFormat(ByVal formatType As Type) As Object Implements IFormatProvider.GetFormat
            If formatType Is GetType(ICustomFormatter) Then
                Return Me
            End If
            Return Nothing
        End Function
        Public Function Format(ByVal fmt As String, ByVal arg As Object, ByVal formatProvide As IFormatProvider) As String Implements ICustomFormatter.Format
            If TypeOf arg Is System.DBNull Then
                Return String.Empty
            End If
            If TypeOf arg Is TimeSpan Then
                Dim evaluator As MatchEvaluator = New MatchEvaluator(AddressOf EvaluateMatch)
                'Dim timeSpan As TimeSpan = CType(arg, TimeSpan)
                _timeSpan = CType(arg, TimeSpan)
                Return _formatParse.Replace(fmt, evaluator) '   GetMatchEvaluator(timeSpan))
            Else
                Dim formattable As IFormattable = CType(arg, IFormattable)
                If formattable IsNot Nothing Then
                    Return formattable.ToString(fmt, formatProvide)
                End If
    
                If arg IsNot Nothing Then
                    Return arg.ToString()
                End If
    
                Return String.Empty
                'Return IIf(arg IsNot Nothing, arg.ToString(), String.Empty)
            End If
        End Function
        'Private Function GetMatchEvaluator(ByVal timeSpan As TimeSpan) As MatchEvaluator
        '    Return Function(m) EvaluateMatch(m, timeSpan)
        'End Function
        Private Function EvaluateMatch(ByVal match As Match) As String ', ByVal timeSpan As TimeSpan) As String
            Select Case match.Value
                Case "dd"
                    'Return TimeSpan.Days.ToString("00")
                    Return _timeSpan.Days.ToString("00")
                Case "d"
                    'Return TimeSpan.Days.ToString("0")
                    Return _timeSpan.Days.ToString("0")
                Case "hh"
                    'Return TimeSpan.Hours.ToString("00")
                    Return _timeSpan.Hours.ToString("00")
                Case "h"
                    'Return TimeSpan.Hours.ToString("0")
                    Return _timeSpan.Hours.ToString("0")
                Case "mm"
                    'Return TimeSpan.Minutes.ToString("00")
                    Return _timeSpan.Minutes.ToString("00")
                Case "m"
                    'Return TimeSpan.Minutes.ToString("0")
                    Return _timeSpan.Minutes.ToString("0")
                Case "ss"
                    'Return TimeSpan.Seconds.ToString("00")
                    Return _timeSpan.Seconds.ToString("00")
                Case "s"
                    'Return TimeSpan.Seconds.ToString("0")
                    Return _timeSpan.Seconds.ToString("0")
                Case "fffffff"
                    'Return (TimeSpan.Milliseconds * 10000).ToString("0000000")
                    Return (_timeSpan.Milliseconds * 10000).ToString("0000000")
                Case "ffffff"
                    'Return (TimeSpan.Milliseconds * 1000).ToString("000000")
                    Return (_timeSpan.Milliseconds * 1000).ToString("000000")
                Case "fffff"
                    'Return (TimeSpan.Milliseconds * 100).ToString("00000")
                    Return (_timeSpan.Milliseconds * 100).ToString("00000")
                Case "ffff"
                    'Return (TimeSpan.Milliseconds * 10).ToString("0000")
                    Return (_timeSpan.Milliseconds * 10).ToString("0000")
                Case "fff"
                    'Return TimeSpan.Milliseconds.ToString("000")
                    Return _timeSpan.Milliseconds.ToString("000")
                Case "ff"
                    'Return (TimeSpan.Milliseconds / 10).ToString("00")
                    Return (_timeSpan.Milliseconds / 10).ToString("00")
                Case "f"
                    'Return (TimeSpan.Milliseconds / 100).ToString("0")
                    Return (_timeSpan.Milliseconds / 100).ToString("0")
                Case Else
                    Return match.Value
            End Select
        End Function
    End Class
    
    

     


    m es una expression lambda disponible desde VS2008 y superior...

    como no tengo VS2005 se me hace dificil encontrar una equivalencia pero lo mejor que puede hacer es crear un delegado para resolver el problema.

    pruebalo y me avisas si te funciono.

    Salu2,


    Marvin E. Pineda

      ComboBoxMultiColumns

      NetBarControl

      TextEditor




    martes, 04 de octubre de 2011 17:17

Todas las respuestas

  • hola

    me genera desconfianza ese tipo de dato time que comentas, no por como lo trabaje sql server, sino de la forma en que lo asignes en el codigo

    como sabras en .net no hay un tipo de solo hora, salvo que uses un TimeSpan, pero no has comentado que uses este

    por lo tanto me genera dudas como es que recuperas y asignas ese campo

    si haces

            Dim time As DateTime = Convert.ToDateTime("14:20:15")

            txtNumero.Text = time.ToString("HH:mm")

    funciona ?

    lo que habria que validar ese al cargar el datatable que tipo de dato asigna al campo de la hora, porque al no haber un tipo de hora sola seguro le deje un string y si a este le defines formato no aplciara, el string no lleva formato, solo los tipos de datos al convertir a string

    prueba desde la query en sql de convertir ese campo hora al DATE

    SELECT CONVERT(datetime, hora) As hora

    con esto tendras la hora en un tipo de dato que .net si puede definir, y al cual luego le aplicas formato

    saludos


    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina
    lunes, 03 de octubre de 2011 10:58
  • Gracias, Leandro.

    Efectivamente, el enlace de datos devuelve un TimeSpan. Lo que no entiendo es por qué no se muestra correctamente ese timespan con la cadena de formato que le asigno, y necesariamente muestra los segundos.

    Hasta ahora no me había pasado que tras un evento bindingcomplete no se formatearan correctamente los datos de fecha u hora. Esa es realmente mi pregunta.


    Miguel Ángel Muñoz
    lunes, 03 de octubre de 2011 11:45
  • Gracias, Leandro.

    Efectivamente, el enlace de datos devuelve un TimeSpan. Lo que no entiendo es por qué no se muestra correctamente ese timespan con la cadena de formato que le asigno, y necesariamente muestra los segundos.

    Hasta ahora no me había pasado que tras un evento bindingcomplete no se formatearan correctamente los datos de fecha u hora. Esa es realmente mi pregunta.


    Miguel Ángel Muñoz

    Hola Miguel,

    es correcto un campo time(7) del SQL Server 2008 sera TimeSpan en .Net Framework, ahora!!!, el problema es que TimeSpan no es una fecha poreso no acepta el formato, pero para eso existen opciones y la que yo encontre es esta:

    Format TimeSpan in DataGridView Column

    lastimosa mente esta en C#, para aplicar el código deberas crear tu clase que herede de DataGridViewColumn y DataGridViewTextBoxCell, ademas el menciona usar el CellFormatting para pintar el formato correcto en la celda pero esto tambien lo puedes resolver en la clase que herede de DataGridViewTextBoxCell sobre escribiendo el metodo protegido GetFormattedValue y el metodo publico ParseFormattedValue, bueno este ultimo lo tube que sobreescribir ya que editar la columna y al terminar de editar la cuadricula llama a este metodo.

    se que esta en C# pero existen convertidores de código de C# a VB y viceverza.

    cualquier duda o ayuda que necesites estaremos poraqui.

    Salu2,


    Marvin E. Pineda

      ComboBoxMultiColumns

      NetBarControl

      TextEditor



    lunes, 03 de octubre de 2011 13:41
  • Gracias Marvin.

    La verdad es que no sé cómo hacerlo. He estado intentándolo desde ayer y no tengo conocimientos suficientes para armar esa clase que mencionas (que herede de DataGridViewColumn y DataGridViewTextBoxCell). Al no ser el DataGridViewTextBoxCell un control 'independiente' no puedo acceder a sus eventos. Si pudieras indicarme por dónde debo empezar, te lo agradecería.

     


    Miguel Ángel Muñoz
    martes, 04 de octubre de 2011 3:50
  • pero has intentado como comente de aplciar un CONVERT() en la query de sql y no devolver directo el campo de hora directamente

    sino que convertir a datetime directo alli en la db y entocnes si al pasarle el datetime aplique el formato

    revisa los metodos de conversion del link

     

    para qeu veas como aplciar la conversion y devolver la fecha

    saludos


    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina
    martes, 04 de octubre de 2011 4:06
  • Creo que no entiendo lo que propones en la query, Leandro.

    En la aplicación tengo un dataset que ha recogido la estructura de la tabla tal cual viene de la BD. ¿Cómo tengo que aplicar ese cambio?


    Miguel Ángel Muñoz
    martes, 04 de octubre de 2011 10:14
  • Hola Miguel Angel,

    Fijate en esta select 

    DECLARE @Tiempo TIME
    SET @Tiempo= GETDATE()
    SELECT CONVERT(VARCHAR(5),@Tiempo,108) AS Tiempo
    

    1. Declaro una variable de tipo TIME

    2.Asigno a esa variable la funcion GETDATE() que devuelve la fecha del sistema.

    3.Convierto esa variable a varchar(5).

    Lo que tienes que hacer es lo siguiente.

    SELECT CONVERT(VARCHAR(5),CAMPO,108) FROM TABLA.

    Saludos,


    phurtado
    martes, 04 de octubre de 2011 10:30
  • hola

    en realidad proponia convertirlo a datetime en lugar de un varchar, ya que imagine el formato se podia aplciar en el grid para mostrar solo la hora

     

    es mas veo que el priemr mensaje que deje ni lo viste, porque aplli reflejo la idea

    SELECT CONVERT(datetime, hora) As hora

    saludos


    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina
    martes, 04 de octubre de 2011 12:31
  • Gracias Marvin.

    La verdad es que no sé cómo hacerlo. He estado intentándolo desde ayer y no tengo conocimientos suficientes para armar esa clase que mencionas (que herede de DataGridViewColumn y DataGridViewTextBoxCell). Al no ser el DataGridViewTextBoxCell un control 'independiente' no puedo acceder a sus eventos. Si pudieras indicarme por dónde debo empezar, te lo agradecería.

     


    Miguel Ángel Muñoz

    bueno, como usas VS2005 y yo estoy usando VS2008 o VS2010 te paso el código para que hagas un copy / paste,

    create una clase en tu projecto con el nombre de "DataGridViewTimeSpanColumn" y dentro de esta clase pegas este código, recompilas, create un nuevo formulario, le agregas un DataGridView, ha este le agregas una columna cuyo tipo sera "DataGridViewTimeSpanColumn"

    luego en Load del formulario puedes create una tabla con una columna tipo TimeSpan

    ejemplo:

        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    
            Dim tabla As New DataTable()
            tabla.Columns.Add(New DataColumn("hora", GetType(TimeSpan)))
    
            Dim row As DataRow = tabla.NewRow()
            row("hora") = New TimeSpan(8, 30, 0)
            tabla.Rows.Add(row)
    
            DataGridView1.AutoGenerateColumns = False
            DataGridView1.DataSource = tabla
    
        End Sub
    

    y listo... ahora!!!!... esta clase no implementa un editor, como .Net Framework no tiene un control para editar TimeSpan tendras que crearte tu uno para tal objetivo y para usarlo en el DataGridView tendras que create una clase que herede de IDataGridViewEditingControl y de tu control personalizado para editar TimeSpan.

    jejejeje... suena dificil eh!!!... pero los resultados son excelentes...

    Imports System.Text.RegularExpressions
    
    Public Class DataGridViewTimeSpanColumn
        Inherits DataGridViewColumn
    
        Public Sub New()
            MyBase.New(New DataGridViewTimeSpanCell())
    
        End Sub
        Public Overrides Property CellTemplate As System.Windows.Forms.DataGridViewCell
            Get
                Return MyBase.CellTemplate
            End Get
            Set(ByVal value As System.Windows.Forms.DataGridViewCell)
                If value IsNot Nothing And Not value.GetType().IsAssignableFrom(GetType(DataGridViewTimeSpanCell)) Then
                    Throw New InvalidCastException("")
                End If
                MyBase.CellTemplate = value
            End Set
        End Property
    
    End Class
    Public Class DataGridViewTimeSpanCell
        Inherits DataGridViewTextBoxCell
    
        Public Sub New()
            MyBase.New()
            Style.FormatProvider = New TimeSpanFormatter()
            Style.Format = "hh:mm"
        End Sub
        Public Overrides ReadOnly Property ValueType As System.Type
            Get
                Return GetType(TimeSpan)
            End Get
        End Property
        Public Overrides ReadOnly Property DefaultNewRowValue As Object
            Get
                Return New TimeSpan()
            End Get
        End Property
        Protected Overrides Function GetFormattedValue(ByVal value As Object, ByVal rowIndex As Integer, ByRef cellStyle As System.Windows.Forms.DataGridViewCellStyle, ByVal valueTypeConverter As System.ComponentModel.TypeConverter, ByVal formattedValueTypeConverter As System.ComponentModel.TypeConverter, ByVal context As System.Windows.Forms.DataGridViewDataErrorContexts) As Object
            If TypeOf value Is TimeSpan? Then
                If CType(value, TimeSpan?).Value.CompareTo(New TimeSpan) = 0 Then
                    Return String.Empty
                End If
            End If
            Dim formatter As ICustomFormatter = CType(cellStyle.FormatProvider, ICustomFormatter)
            If formatter IsNot Nothing Then
                Dim formattedValue As String = formatter.Format(cellStyle.Format, value, cellStyle.FormatProvider)
                Return formattedValue
            End If
            Return MyBase.GetFormattedValue(value, rowIndex, cellStyle, valueTypeConverter, formattedValueTypeConverter, context)
        End Function
    End Class
    
    Class TimeSpanFormatter
        Implements IFormatProvider, ICustomFormatter
    
        Private _formatParse As Regex
    
        Sub New()
            _formatParse = New Regex("d{1,2}|h{1,2}|m{1,2}|s{1,2}|f{1,7}", RegexOptions.Compiled)
        End Sub
        Public Function GetFormat(ByVal formatType As Type) As Object Implements IFormatProvider.GetFormat
            If formatType Is GetType(ICustomFormatter) Then
                Return Me
            End If
            Return Nothing
        End Function
        Public Function Format(ByVal fmt As String, ByVal arg As Object, ByVal formatProvide As IFormatProvider) As String Implements ICustomFormatter.Format
            If TypeOf arg Is System.DBNull Then
                Return String.Empty
            End If
            If TypeOf arg Is TimeSpan Then
                Dim timeSpan As TimeSpan = CType(arg, TimeSpan)
                Return _formatParse.Replace(fmt, GetMatchEvaluator(timeSpan))
            Else
                Dim formattable As IFormattable = CType(arg, IFormattable)
                If formattable IsNot Nothing Then
                    Return formattable.ToString(fmt, formatProvide)
                End If
    
                If arg IsNot Nothing Then
                    Return arg.ToString()
                End If
    
                Return String.Empty
                'Return IIf(arg IsNot Nothing, arg.ToString(), String.Empty)
            End If
        End Function
        Private Function GetMatchEvaluator(ByVal timeSpan As TimeSpan) As MatchEvaluator
            Return Function(m) EvaluateMatch(m, timeSpan)
        End Function
        Private Function EvaluateMatch(ByVal match As Match, ByVal timeSpan As TimeSpan) As String
            Select Case match.Value
                Case "dd"
                    Return timeSpan.Days.ToString("00")
                Case "d"
                    Return timeSpan.Days.ToString("0")
                Case "hh"
                    Return timeSpan.Hours.ToString("00")
                Case "h"
                    Return timeSpan.Hours.ToString("0")
                Case "mm"
                    Return timeSpan.Minutes.ToString("00")
                Case "m"
                    Return timeSpan.Minutes.ToString("0")
                Case "ss"
                    Return timeSpan.Seconds.ToString("00")
                Case "s"
                    Return timeSpan.Seconds.ToString("0")
                Case "fffffff"
                    Return (timeSpan.Milliseconds * 10000).ToString("0000000")
                Case "ffffff"
                    Return (timeSpan.Milliseconds * 1000).ToString("000000")
                Case "fffff"
                    Return (timeSpan.Milliseconds * 100).ToString("00000")
                Case "ffff"
                    Return (timeSpan.Milliseconds * 10).ToString("0000")
                Case "fff"
                    Return timeSpan.Milliseconds.ToString("000")
                Case "ff"
                    Return (timeSpan.Milliseconds / 10).ToString("00")
                Case "f"
                    Return (timeSpan.Milliseconds / 100).ToString("0")
                Case Else
                    Return match.Value
            End Select
        End Function
    
    
    End Class
    
    Salu2,


    Marvin E. Pineda

      ComboBoxMultiColumns

      NetBarControl

      TextEditor



    martes, 04 de octubre de 2011 14:35
  • A esto llamo yo una buena ayuda. Muy agradecido, Marvin. Voy a ponerme a problarlo enseguida.

    También quiero agradecer a Leandro su aportación: cuando leí las respuestas (que las leo todas), me decanto por lo que en principio me parece más simple, y me puse a probar la de Marvin. Al no conseguir nada, lo dejé pendiente para hoy, y cuando por la mañana ví que había una nueva respuesta de Marvin, quise seguir por ahí.

    Creo entender de tu propuesta que el dataadapter de mi dataset, debo editarlo y modificar la select según indicas. Pero mi duda es si se hace de esa manera, ¿actualizará convenientemente el campo time(7)?

    Gracias de nuevo a ambos.


    Miguel Ángel Muñoz
    martes, 04 de octubre de 2011 15:36
  • A esto llamo yo una buena ayuda. Muy agradecido, Marvin. Voy a ponerme a problarlo enseguida.

    También quiero agradecer a Leandro su aportación: cuando leí las respuestas (que las leo todas), me decanto por lo que en principio me parece más simple, y me puse a probar la de Marvin. Al no conseguir nada, lo dejé pendiente para hoy, y cuando por la mañana ví que había una nueva respuesta de Marvin, quise seguir por ahí.

    Creo entender de tu propuesta que el dataadapter de mi dataset, debo editarlo y modificar la select según indicas. Pero mi duda es si se hace de esa manera, ¿actualizará convenientemente el campo time(7)?

    Gracias de nuevo a ambos.


    Miguel Ángel Muñoz

    con respecto a la parte de aplicar el cambio como lo plantea Leandro o Pedro, te dire que si funciona ya que cuando impactas contra el registro lo que hace es tomar solo la parte time del DateTime para reemplazar el campo y esto lo puedes comprobar directamente en sql haciendo una prueba controlada.

    ejemplo:

    UPDATE <Tabla> SET hora = GETDATE()

    donde hora debera ser un campo tipo time(7)

    tambien puedes usar un String con el formato adecuado

    UPDATE <Tabla> SET hora = '10:50:00'

    y veras que de ambas maneras funciona sin marcar error

    Salu2,

     

     


    Marvin E. Pineda

      ComboBoxMultiColumns

      NetBarControl

      TextEditor



    martes, 04 de octubre de 2011 15:45
  • Voy a ello en cuanto acabe de plantearte lo siguiente:
    Hay una línea que no me funciona, y es vital para el resultado.
    El compilador me señala la palabra Function(m) ("se esperaba una expresion")
    ¿Cómo lo arreglo?
        Private Function GetMatchEvaluator(ByVal timeSpan As TimeSpan) As MatchEvaluator
    		Return Function(m) EvaluateMatch(m, timeSpan)
        End Function
    
    
    Mil disculpas a Pedro por no haberlo citado antes. Lei tu respuesta esta mañana en el trabajo y casi te había olvidado.

    Miguel Ángel Muñoz
    martes, 04 de octubre de 2011 16:12
  • Voy a ello en cuanto acabe de plantearte lo siguiente:
    Hay una línea que no me funciona, y es vital para el resultado.
    El compilador me señala la palabra Function(m) ("se esperaba una expresion")
    ¿Cómo lo arreglo?
        Private Function GetMatchEvaluator(ByVal timeSpan As TimeSpan) As MatchEvaluator
    		Return Function(m) EvaluateMatch(m, timeSpan)
        End Function
    
    
     
    Mil disculpas a Pedro por no haberlo citado antes. Lei tu respuesta esta mañana en el trabajo y casi te había olvidado.

    Miguel Ángel Muñoz

    incluistes el Import al inicio?

    Imports System.Text.RegularExpressions

    caso contrario, bueno!!!!... como es VS2005 abria que buscar la equivalencia a ese comando

    Salu2,


    Marvin E. Pineda

      ComboBoxMultiColumns

      NetBarControl

      TextEditor



    martes, 04 de octubre de 2011 16:14
  • El imports está en la primera línea tal cual tú lo reportaste.

    Se ve que esta versión de VS no lo acepta, pero ahí me pierdo.


    Miguel Ángel Muñoz
    martes, 04 de octubre de 2011 16:17
  • El imports está en la primera línea tal cual tú lo reportaste.

    Se ve que esta versión de VS no lo acepta, pero ahí me pierdo.


    Miguel Ángel Muñoz

    Prueba este código

    Private Function GetMatchEvaluator(timeSpan As TimeSpan) As MatchEvaluator
            m => EvaluateMatch(m, timeSpan)
            Return m
     End Function
    


    este lo obtube usando un covertidor de C# a VB, pero en VS2010 marca error, pero pruebalo tu en VS2005 a ver si te funciona.

    Salu2,


    Marvin E. Pineda

      ComboBoxMultiColumns

      NetBarControl

      TextEditor



    martes, 04 de octubre de 2011 16:20
  • No funciona. Realmente lo que no entiendo es de dónde sale esa variable m. De verdad que no lo pillo.
    Miguel Ángel Muñoz
    martes, 04 de octubre de 2011 16:28
  • Prueba reemplazando la class TimeSpanFormatter por esta nueva.

     

    Class TimeSpanFormatter
        Implements IFormatProvider, ICustomFormatter
    
        Private _formatParse As Regex
        Private _timeSpan As TimeSpan
    
        Sub New()
            _formatParse = New Regex("d{1,2}|h{1,2}|m{1,2}|s{1,2}|f{1,7}", RegexOptions.Compiled)
        End Sub
        Public Function GetFormat(ByVal formatType As Type) As Object Implements IFormatProvider.GetFormat
            If formatType Is GetType(ICustomFormatter) Then
                Return Me
            End If
            Return Nothing
        End Function
        Public Function Format(ByVal fmt As String, ByVal arg As Object, ByVal formatProvide As IFormatProvider) As String Implements ICustomFormatter.Format
            If TypeOf arg Is System.DBNull Then
                Return String.Empty
            End If
            If TypeOf arg Is TimeSpan Then
                Dim evaluator As MatchEvaluator = New MatchEvaluator(AddressOf EvaluateMatch)
                'Dim timeSpan As TimeSpan = CType(arg, TimeSpan)
                _timeSpan = CType(arg, TimeSpan)
                Return _formatParse.Replace(fmt, evaluator) '   GetMatchEvaluator(timeSpan))
            Else
                Dim formattable As IFormattable = CType(arg, IFormattable)
                If formattable IsNot Nothing Then
                    Return formattable.ToString(fmt, formatProvide)
                End If
    
                If arg IsNot Nothing Then
                    Return arg.ToString()
                End If
    
                Return String.Empty
                'Return IIf(arg IsNot Nothing, arg.ToString(), String.Empty)
            End If
        End Function
        'Private Function GetMatchEvaluator(ByVal timeSpan As TimeSpan) As MatchEvaluator
        '    Return Function(m) EvaluateMatch(m, timeSpan)
        'End Function
        Private Function EvaluateMatch(ByVal match As Match) As String ', ByVal timeSpan As TimeSpan) As String
            Select Case match.Value
                Case "dd"
                    'Return TimeSpan.Days.ToString("00")
                    Return _timeSpan.Days.ToString("00")
                Case "d"
                    'Return TimeSpan.Days.ToString("0")
                    Return _timeSpan.Days.ToString("0")
                Case "hh"
                    'Return TimeSpan.Hours.ToString("00")
                    Return _timeSpan.Hours.ToString("00")
                Case "h"
                    'Return TimeSpan.Hours.ToString("0")
                    Return _timeSpan.Hours.ToString("0")
                Case "mm"
                    'Return TimeSpan.Minutes.ToString("00")
                    Return _timeSpan.Minutes.ToString("00")
                Case "m"
                    'Return TimeSpan.Minutes.ToString("0")
                    Return _timeSpan.Minutes.ToString("0")
                Case "ss"
                    'Return TimeSpan.Seconds.ToString("00")
                    Return _timeSpan.Seconds.ToString("00")
                Case "s"
                    'Return TimeSpan.Seconds.ToString("0")
                    Return _timeSpan.Seconds.ToString("0")
                Case "fffffff"
                    'Return (TimeSpan.Milliseconds * 10000).ToString("0000000")
                    Return (_timeSpan.Milliseconds * 10000).ToString("0000000")
                Case "ffffff"
                    'Return (TimeSpan.Milliseconds * 1000).ToString("000000")
                    Return (_timeSpan.Milliseconds * 1000).ToString("000000")
                Case "fffff"
                    'Return (TimeSpan.Milliseconds * 100).ToString("00000")
                    Return (_timeSpan.Milliseconds * 100).ToString("00000")
                Case "ffff"
                    'Return (TimeSpan.Milliseconds * 10).ToString("0000")
                    Return (_timeSpan.Milliseconds * 10).ToString("0000")
                Case "fff"
                    'Return TimeSpan.Milliseconds.ToString("000")
                    Return _timeSpan.Milliseconds.ToString("000")
                Case "ff"
                    'Return (TimeSpan.Milliseconds / 10).ToString("00")
                    Return (_timeSpan.Milliseconds / 10).ToString("00")
                Case "f"
                    'Return (TimeSpan.Milliseconds / 100).ToString("0")
                    Return (_timeSpan.Milliseconds / 100).ToString("0")
                Case Else
                    Return match.Value
            End Select
        End Function
    End Class
    
    

     


    m es una expression lambda disponible desde VS2008 y superior...

    como no tengo VS2005 se me hace dificil encontrar una equivalencia pero lo mejor que puede hacer es crear un delegado para resolver el problema.

    pruebalo y me avisas si te funciono.

    Salu2,


    Marvin E. Pineda

      ComboBoxMultiColumns

      NetBarControl

      TextEditor




    martes, 04 de octubre de 2011 17:17
  • Genial, Marvin. Ahora sí. Aunque hay una pequeña pega: cuando el dato a presentar son las cero horas del día (lo que en España decimos las doce de la noche), no muestra nada. He probado con las 00:01 e incluso las 00:00:01 y muestra ambas. Lógicamente, esta última sí la representa como las 00:00 porque aunque le marco que pasa un segundo de esta hora, he quitado los segundos de la cadena a representar. Intentaré buscar una solución a este último escollo, pero a grandes rasgos, la solución está servida. Sinceramente, gracias.

    Respondiendo a Leandro y a Pedro, el diseñador de dataset no acepta el cambio en la select del tableadapter, porque el campo forma parte de la clave principal. He probado con otro campo time(7) de la misma tabla haciendo un CONVERT(VARCHAR(5),MiCampo,108) y al hacer una vista previa de datos, no muestra nada. Había pensado como solución a mi problema, añadir en la select una columna calculada utilizando la solución que ambos proponéis, pero he utilizado muchos campos time(7) en el diseño de la BD y quería algo más definitivo, tal como un componente personalizado, ya que en caso contrario, podría ocultar en todas las rejillas de datos el campo real y mostrar la columna calculada. Sería un trabajo extra pero funcionaría igualmente.

    Como siempre, doy las gracias por colaborar en la solución de este hilo.


    Miguel Ángel Muñoz
    miércoles, 05 de octubre de 2011 3:10
  • excelente... lo que podrias hacer en este caso en el metodo EvaluateMatch convertir las horas, así, si es mayor a 12 entonces (horas - 12).ToString("00") y si hora es igual a 0 entonces (12).ToString("00"), bueno!!! tu sabras ya como colocar esto en codigo, solo estoy ejemplificando.... para así mostrar la hora como la quieres, porque recuerda que estas forzando aplicar un formato al TimeSpan, pero en si el TimeSpan es un acumulador de tiempo no lo formatea por si mismo....

    Salu2,


    Marvin E. Pineda

      ComboBoxMultiColumns

      NetBarControl

      TextEditor



    miércoles, 05 de octubre de 2011 3:32
  • He encontrado el problema y la solución.

    Está en la clase DataGridViewTimeSpanCell, concretamente en la función GetFormattedValue, cuando bifurca el código al encontrar la condición de que el valor del timespan sea cero. Obviamente, las cero horas es siempre este caso. Lo resuelvo forzando a retornar el valor "00:00". Te muestro el código (te ruego me indiques si crees que puede darme problemas):

            If TypeOf value Is TimeSpan Then
                If CType(value, TimeSpan).CompareTo(New TimeSpan) = 0 Then
                    Return String.Empty
                End If
            End If

     

    este es el cambio que introduzco

     

            If TypeOf value Is TimeSpan Then
                If CType(value, TimeSpan).CompareTo(New TimeSpan) = 0 Then
                    'Return String.Empty
                    Return "00:00"
                End If
            End If

    Miguel Ángel Muñoz
    miércoles, 05 de octubre de 2011 4:06
  • He encontrado el problema y la solución.

    Está en la clase DataGridViewTimeSpanCell, concretamente en la función GetFormattedValue, cuando bifurca el código al encontrar la condición de que el valor del timespan sea cero. Obviamente, las cero horas es siempre este caso. Lo resuelvo forzando a retornar el valor "00:00". Te muestro el código (te ruego me indiques si crees que puede darme problemas):

            If TypeOf value Is TimeSpan Then
                If CType(value, TimeSpan).CompareTo(New TimeSpan) = 0 Then
                    Return String.Empty
                End If
            End If

     

    este es el cambio que introduzco

     

            If TypeOf value Is TimeSpan Then
                If CType(value, TimeSpan).CompareTo(New TimeSpan) = 0 Then
                    'Return String.Empty
                    Return "00:00"
                End If
            End If

    Miguel Ángel Muñoz

    mmm... no, no te dara problema, como es cuestion de gustos, yo implemento este código y en mi caso yo quiero que devuelva empty en lugar de 00:00, pero no te dara problema porque lo que la funcion hace es precisamente eso, formatear el valor de la celda para mostrarlo correcta mente y si tu quieres que aparesca así 00:00 pues esta bien.

    Salu2,


    Marvin E. Pineda

      ComboBoxMultiColumns

      NetBarControl

      TextEditor




    miércoles, 05 de octubre de 2011 13:37
  • ahora!!!!... te dire que el código no esta terminado, según lo vayas implementando vas a tener que irle haciendo ajustes...

    Salu2,


    Marvin E. Pineda

      ComboBoxMultiColumns

      NetBarControl

      TextEditor



    miércoles, 05 de octubre de 2011 13:39
  • A ver...

    ¿Qué ajustes?

    Gracias Marvin.


    Miguel Ángel Muñoz
    miércoles, 05 de octubre de 2011 16:33
  • Tengo otro problema similar al del datagridview respecto al formato. Tengo creados varios controles personalizados. Uno de ellos sirve para mostrar la hora. La clase deriva de Textbox y he codificado varios eventos para que al estar enlazado a un campo de datos, muestre este con el formato habitual de HH:mm.

    Se comporta exactamente igual que el datagridview, mostrando siempre los segundos (HH:mm:ss). El caso es que no sé que evento debo controlar para obligarlo de alguna manera a que formatee el dato como yo quiero. ¿Puedes ayudarme en esto?


    Miguel Ángel Muñoz
    jueves, 06 de octubre de 2011 6:25
  • Tengo otro problema similar al del datagridview respecto al formato. Tengo creados varios controles personalizados. Uno de ellos sirve para mostrar la hora. La clase deriva de Textbox y he codificado varios eventos para que al estar enlazado a un campo de datos, muestre este con el formato habitual de HH:mm.

    Se comporta exactamente igual que el datagridview, mostrando siempre los segundos (HH:mm:ss). El caso es que no sé que evento debo controlar para obligarlo de alguna manera a que formatee el dato como yo quiero. ¿Puedes ayudarme en esto?


    Miguel Ángel Muñoz

    si, pero para este ya tendras que crearte un nuevo hilo o nueva pregunta.

    Salu2,


    Marvin E. Pineda

      ComboBoxMultiColumns

      NetBarControl

      TextEditor



    jueves, 06 de octubre de 2011 13:01
  • como tambien tendras que dar por cerrada esta....

    Salu2,


    Marvin E. Pineda

      ComboBoxMultiColumns

      NetBarControl

      TextEditor



    jueves, 06 de octubre de 2011 13:02