views:

4008

answers:

2

Hi,

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>

Thanks

+2  A: 

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;
    }
}
sipwiz
A: 

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".

Rabbi