Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bind DateTime to Date and Time EditFields

i am trying to build a gui that includes editing a DateTime value of an object. The DateTime Property has binding to a DataPicker and a normal TextBox for the Time. When i change the value in the Time TextBox the value wirtten in the DateTime Property is Today with the entered Time instead of just updating the Time, preserving the original Date.

How can i implement a Time TextBox that only changes the DateTime time but not the date?

Current Binding:

<TextBlock>Time</TextBlock>
<TextBox Template="{StaticResource RoundedTextBoxTemplate}">
    <Binding Path="Delivery.Date" StringFormat="HH:mm">
        <Binding.ValidationRules>
            <v:IsValidTimeRule />
        </Binding.ValidationRules>
    </Binding>
</TextBox>

2 Answers

The only way I could think of to do it is to have a DateTime property where you only allow the setter change the time.

XAML:

<UserControl.Resources> 
    <mine:DateTimeConverter x:Key="MyDateTimeConverter" />
</UserControl.Resources>    
<Grid x:Name="LayoutRoot">
    <TextBox x:Name="myTextBox" Text="{Binding Path=TestDateTime, Converter={StaticResource MyDateTimeConverter}, Mode=TwoWay}" />
</Grid>

C# Code behind:

 public partial class Page : UserControl
 {
      private TestClass m_testClass = new TestClass();

      public Page()
      {
           InitializeComponent();
           myTextBox.DataContext = m_testClass;
      }
  }

C# TestClass where the property setter restriction is used:

public class TestClass : INotifyPropertyChanged
{
    private DateTime m_testDateTime = DateTime.Now;
    public DateTime TestDateTime
    {
        get { return m_testDateTime; }
        set
        {
            m_testDateTime = m_testDateTime.Date.Add(value.TimeOfDay);
            PropertyChanged(this, new PropertyChangedEventArgs("TestDateTime"));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged = (t, e) => {};
}

C# IValueConverter:

public class DateTimeConverter : IValueConverter
{
    public object Convert(object value,
                       Type targetType,
                       object parameter,
                       CultureInfo culture)
    {
        DateTime date = (DateTime)value;
        return date.ToString("HH:mm");
    }

    public object ConvertBack(object value,
                              Type targetType,
                              object parameter,
                              CultureInfo culture)
    {
        string strValue = value.ToString();
        DateTime resultDateTime;
        if (DateTime.TryParse(strValue, out resultDateTime))
        {
            return resultDateTime;
        }
        return value;
    }
}
like image 146
sipsorcery Avatar answered Sep 16 '25 01:09

sipsorcery


I extended sipWiz's solution a bit but I left it all in my Model class

I created two fields 1. StartDay 2. StartTime which both access my primary field StartDate behid the scenes.

public DateTime? StartTime
{
    get
    {
        return StartDate;
    }
    set
    {
        if (StartDate == null) StartDate = DateTime.Today;
        StartDate = StartDate.Value.Date.Add(value.HasValue ? value.Value.TimeOfDay: TimeSpan.Zero);
    }
}
public DateTime? StartDay
{
    get { return StartDate; }
    set
    {
        DateTime BaseDate = value.HasValue ? value.Value : DateTime.MinValue;
        StartDate = BaseDate.Date.Add(StartDate.HasValue ? StartDate.Value.TimeOfDay : TimeSpan.Zero);
    }
}

Then you can Bind the DatePicker to the day field and the TextBox to the time field with StringFormat="HH:mm".

like image 37
Rabbi Avatar answered Sep 16 '25 01:09

Rabbi