2012-03-14 7 views
6

Ho un DateTimePicker che ho impostato per mostrare solo il mese e l'anno come segue:Come posso fare in modo che una selezione data/ora contenga sempre l'ultimo giorno del mese mentre mostra solo il mese e l'anno?

myDateTimePicker.Format = DateTimePickerFormat.Custom; 
myDateTimePicker.CustomFormat = "MMMM yyyy"; 
myDateTimePicker.ShowUpDown = true; 

Tuttavia, voglio il valore alla data di essere sempre l'ultimo giorno del mese selezionato, così mi sono messo il DateTime in caso ValueChanged utilizzando:

DateTime selectedDate = myDateTimePicker.Value; 
DateTime lastDayOfMonth = new DateTime(
    selectedDate.Year, 
    selectedDate.Month, 
    DateTime.DaysInMonth(selectedDate.Year, selectedDate.Month)); 
myDateTimePicker.Value = lastDayOfMonth; 

il problema è, se ho un mese come marzo selezionato, e io modificare il mese a febbraio utilizzando i tasti su/giù controlli, ottengo il seguente errore prima che io possa gestire l'evento ValueChanged:

ArgumentOutOfRangeException was unhandled 
Year, Month, and Day parameters describe an un-representable DateTime. 

Questo è comprensibile perché la data era il 31 marzo e viene modificata in data 31 febbraio che è una data non valida. Tuttavia, voglio cambiarlo al 28 febbraio (o al 29 febbraio).

Come posso ottenere questo risultato?

+2

questo è un bug nel DateTimePicker. La soluzione è qui: http://social.msdn.microsoft.com/Forums/en-US/winforms/thread/69b10b5b-a034-426e-a045-2bed8a1637a3 –

+0

Dovresti metterlo come risposta, @HansPassant :) –

+0

I già risposto, io non sono schizzinoso su dove :) –

risposta

4

Molto strano, ho provato a riprodurre il problema, e quando passo da marzo a febbraio, il mio controllo non visualizza nulla ... Forse abbiamo diverse versioni di framework, che gestiscono lo stesso errore in modo diverso.

In ogni caso, una soluzione potrebbe essere quella di impostare il selettore datetime al primo di ogni mese, e quando è necessario il valore, si può semplicemente utilizzare il codice come è attualmente:

DateTime lastDayOfMonth = new DateTime(
    selectedDate.Year, 
    selectedDate.Month, 
    DateTime.DaysInMonth(selectedDate.Year, selectedDate.Month)); 

Dal momento che mai usa il valore del giorno del tuo raccoglitore di dattime, puoi semplicemente impostarlo su 1, che darà sempre una data esistente.

Questa soluzione mi lascia in qualche modo un brutto presentimento, dal momento che si sta utilizzando una data diversa dalla data che si ottiene dal proprio controllo - sempre una possibile fonte di errori, IMO. Ricordatevi di mettere commenti nel codice, che spiega il motivo per cui si sta facendo in questo modo ;-)

+0

Grazie a @Treb.Questo è un approccio interessante. Sono d'accordo che è una possibile fonte di bug, quindi da usare con molta attenzione. Se nessuno suggerisce qualcosa di meglio, probabilmente dovrò farlo :-( –

+0

+1, buona soluzione al problema. –

+0

Ho provato a sovrascrivere 'PreProcessMessage' per acquisire il messaggio prima che si accedesse al DateTime interno del controllo, ma non per fortuna, durante i test ho notato che l'evento 'ValueChanged' è stato sparato due volte: prima dalla modifica avviata attraverso il modulo, e in secondo luogo chiamando' dateTimePicker1.Value = lastDayOfMonth; '... – Treb

2

probabilmente userei il 1 ° del mese, come Treb selezionati, ma si estendono DateTimePicker in modo che quando avete fatto queste cose:

MyDateTimePicker.Value

sarebbe fare qualcosa di simile:

get{ 
return value.addMonths(1).addDays(-1) 
} 
+0

Buon suggerimento per estendere DateTimePicker per nascondere la brutta soluzione –

Problemi correlati