WPF Edit hours and minutes of a DateTime
I have 3 TextBoxes to edit a DateTime. What is important to notice is that those 2 TextBoxes are editing the hour and minutes of the first TextBox DateTime value. One to edit the Date and 2 to edit hour and minutes. How would you do that? The code below doesn't reflect the DateTime changes when editing the hour or minute, because it does ToString("HH") and the DateTime value is lost:
<TextBox Text="{Binding MyDateTime}" />
<!--This cannot work : it's just for clearing purposes -->
<TextBox Text="{Binding MyDateTime, StringFormat=\{0:HH\}}}" />
<TextBox Text="{Binding MyDateTime}, StringFormat=\{0:mm\}}" />
Of course I can have a ViewModel as DataContext w开发者_StackOverflowhere I would solve it programmatically. But I just want to know if there is any possiblity directly in XAML
It is not easily possible with XAML only. There are several possibilities how to solve this:
1. Write custom control or user control that can do this
You could wirte a custom control / user control (e.g. DateTimeTextBox) that has a Property DateTime Value
that your xaml can bind against and that contains logic to convert to the datetime value entered in one of its two textboxes. Instead of two textboxes you could also have something like maskedtextbox.
2. Two dedicated properties in the ViewModel
If you go with MVVM you could give your ViewModel two dedicated properties int DateTimeHours
int DateTimeMinutes
and bind against that:
<TextBox Text="{Binding MyDateTimeHours}" />
<TextBox Text="{Binding MyDateTimeMinutes}" />
Your ViewModel would then merge the two properties to a single DateTime value.
You will need to use a converter with 2way binding and a converter parameter. Save the original hour in the Converter. Then you can update the binding source appropriately.
I appreciate this is an old post, but I came across this today and found another way to handle bindings with date and time.
I created a partial class called dateTime with 4 properties one for the date, 1 for hour and another for minutes. Then a readonly dateTime property that returns a completed date.
Partial Public Class dateTimeValue
Property Dt As Date
Property Hr As Integer
Property Mn As Integer
ReadOnly Property dateTime As Date
Get
Dim d = Dt
d = d.AddHours(d.Hour * -1).AddHours(Hr)
d = d.AddMinutes(d.Minute * -1).AddMinutes(Mn)
d = d.AddSeconds(d.Second * -1)
Return d
End Get
End Property
End Class
Then in the XAML I used a grid layout with the bindings to a DateTimePicker and a couple of ComboBoxes.
<UniformGrid Columns="2">
<TextBlock Text="Date"/>
<DatePicker SelectedDate="{Binding dateTime.Dt}"/>
<TextBlock Text="Time"/>
<WrapPanel>
<ComboBox SelectedValue="{Binding dateTime.Hr}" SelectedValuePath="Content">
<ComboBoxItem>00</ComboBoxItem>
<ComboBoxItem>01</ComboBoxItem>
<ComboBoxItem>02</ComboBoxItem>
.........
<ComboBoxItem>22</ComboBoxItem>
<ComboBoxItem>23</ComboBoxItem>
</ComboBox>
<TextBlock Text=":"/>
<ComboBox SelectedValue="{Binding dateTime.Mn}" SelectedValuePath="Content">
<ComboBoxItem>00</ComboBoxItem>
<ComboBoxItem>15</ComboBoxItem>
<ComboBoxItem>30</ComboBoxItem>
<ComboBoxItem>45</ComboBoxItem>
</ComboBox>
</WrapPanel>
<Button Click="saveTask" Content="Save Task"/>
</UniformGrid>
Then to display the correct date and time in say a textblock you can use
<TextBlock Text="{Binding dateTime.dateTime, StringFormat={}{0:dd MMM yyyy - HH:mm}}"/>
Hope this helps someone else out.
100% MVVM
public class DateTimeConverter : IValueConverter
{
private DateTime _target = DateTime.Now;
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var source = value as DateTime?;
if (source is null) return null;
_target = source.Value;
switch (parameter as string)
{
case "y": return source.Value.Year;
case "m": return source.Value.Month;
case "d": return source.Value.Day;
case "h": return source.Value.Hour;
case "i": return source.Value.Minute;
default: return null;
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
switch (parameter as string)
{
case "y": return new DateTime(System.Convert.ToInt32(value), _target.Month, _target.Day, _target.Hour, _target.Minute, 0);
case "m": return new DateTime(_target.Year, System.Convert.ToInt32(value), _target.Day, _target.Hour, _target.Minute, 0);
case "d": return new DateTime(_target.Year, _target.Month, System.Convert.ToInt32(value), _target.Hour, _target.Minute, 0);
case "h": return new DateTime(_target.Year, _target.Month, _target.Day, System.Convert.ToInt32(value), _target.Minute, 0);
case "i": return new DateTime(_target.Year, _target.Month, _target.Day, _target.Hour, System.Convert.ToInt32(value), 0);
default: return _target;
}
}
}
精彩评论