-1

I am working with C# Winform and Entity Framework,

My question is, Is there a way to bind a TimeSpan property to DateTime control?

I have a DataGridView which is DataBounded to a entity framework DbSet. DbSet has a TimeSpan property which I binded to a DateTime control but displayed as Time only. my Binding is modeled here: Entity Framework - (master detail) how to update Details which on a separate form from Master

Upon execution of the program, no error displayed on build but time is not displayed on the control as well as saving, time is not saved too. :(

Community
  • 1
  • 1
Henry
  • 195
  • 1
  • 16
  • Not quite sure what do you mean by "binded to DateTime control" - AFAIK there is no `DateTime` column type in `DataGridView`. – Ivan Stoev Sep 11 '16 at 17:10
  • Yes, its outside of the `DataGridView`, along with other `TextBox`. If the user selects a row on the `DataGridView`, the values on the `TextBox` also changes based on the row selected, but Time didn't displayed/changed. – Henry Sep 11 '16 at 17:15
  • 1
    I see. So it's `DateTimePicker` control? What property of the control did you bind - `Value`? – Ivan Stoev Sep 11 '16 at 17:31
  • Yes it is, I am binding it to a TimeSpan property on a DbSet on entity framework. – Henry Sep 11 '16 at 17:33

2 Answers2

3

TimeSpan and DateTime are not interchangeable. I believe the simplest solution is create a control derived from DateTimePicker that exposes a TimeSpan property and bind to that.

public class TimePicker : DateTimePicker, System.ComponentModel.INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    public TimePicker()
        : base()
    {
        this.Format = DateTimePickerFormat.Time;
    }

    public TimeSpan Time
    {
        get
        {
            return this.Value.TimeOfDay;
        }
        set
        {
            this.Value = DateTime.Today.Add(value);
        }
    }

    protected override void OnValueChanged(EventArgs eventargs)
    {
        base.OnValueChanged(eventargs);
        if (PropertyChanged != null)
            PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs("Time"));
    }
}

Then you can bind to it something like this:

timePicker1.DataBindings.Add("Time", bindingSource1, "TS", true, DataSourceUpdateMode.OnPropertyChanged);
TnTinMn
  • 11,522
  • 3
  • 18
  • 39
  • Hi @TnTinMn, Thank you for the answer, I tried your solution with the following: 1. Created a new class "TimePicker.cs". 2. On my form.designer.cs, changed this `this.TimeTxt = new System.Windows.Forms.DateTimePicker();` to this `this.TimeTxt = new M3dStation2.Controls.TimePicker();` 3. Changed my bindings to this `this.TimeTxt.DataBindings.Add(new System.Windows.Forms.Binding("Time", this.enrollmedsBindingSource, "Time", false, dataSourceUpdateMode:onPropertyChanged));` but `onPropertyChanged` method is not on the list. Can you guide me on how to properly use your solution? thanks very much:) – Henry Sep 13 '16 at 12:21
  • Hi @TnTinMn, please disregard my previous reply, its just that `DataSourceUpdateMode` is under `System.Windows.Forms` namespace and its not included on the designer by default. The application can now build however upon opening the form `InvalidOperationException` occurs with this message: `Additional information: DataBinding cannot find a row in the list that is suitable for all bindings.`. Thank you in advance for the help :) – Henry Sep 13 '16 at 12:35
  • 1
    @Henry, I never seen that one before and will need to investigate. Is this error happening in the designer or when running or both? – TnTinMn Sep 13 '16 at 13:48
  • Hi TnTinMn, The error occurs upon running, then upon opening of form, on this line of code `this.enrollmedsBindingSource.DataSource = context.enrollmeds.Local;`. Tried to open a record with valid time value, with no record yet, and with record but has null value on time on the database but all of them has the same exception :( – Henry Sep 13 '16 at 13:59
  • 1
    @Henry, This is a strange error. I found [this post](http://stackoverflow.com/a/10908342/2592875) that claims setting the binding parameter `formattingEnabled` to true is the solution (I showed using false). [This post](http://stackoverflow.com/q/12859973/2592875), in the comment from Simon MᶜKenzie, offers some guidance on retrieving more diagnostic info that also involves `formattingEnabled=true`. If those do not help, perhaps post a new question on that error. I do not work with EF, but I did test the control with both a DataTable and BindingList as datasources with no problem. – TnTinMn Sep 13 '16 at 14:55
  • Nice TnTinMn, you got it on the first linked you provided, setting the `formattingEnabled = true` removed the error as well as the binding, I can now view and edit the time on the field.. Thank You Very Much TnTinMn, your a life saver bro.. thanks again :) :) :). ps: can you edit the answer and set the `formattingEnabled` to `true`, so that other viewer can see the correct solution :) :) thanks again :) :) – Henry Sep 13 '16 at 15:32
1

As I undesrand, you have DateTimePicker control with Format set to DateTimePickerFormat.Time and you are binding a TimeSpan to the Value property.

However, the Value property type is DateTime, so the binding silently is failing.

To fix the issue, bind to Text property instead.

Ivan Stoev
  • 195,425
  • 15
  • 312
  • 343
  • Hi Ivan, thanks for your answer, however can you give me sample on how to bind DateTimePicker.Text to timespan? upon checking on my form designer i found code below: `this.TimeTxt.DataBindings.Add(new System.Windows.Forms.Binding("Text", this.enrollmedsBindingSource1, "Time", true));` but i dont know how to update it to use the text instead of value., I am binding via designer. thanks very much :) – Henry Sep 11 '16 at 17:54
  • 2
    If you are binding with code, you should have currently something like `dateTimePicker.DataBindingings.Add("Value", dataSource, "SomeProperty", true)`, so just change "Value" to "Text". If you are using designer, select the control, go to Properties -> Data Bindings, cut what is in Value and paste it into Text. – Ivan Stoev Sep 11 '16 at 18:04
  • Hi Ivan, upon checking binding is already on the Text. Is custom format has role on my problem? `this.TimeTxt.CustomFormat = "hh:mm tt";` `this.TimeTxt.Format = System.Windows.Forms.DateTimePickerFormat.Custom;` – Henry Sep 11 '16 at 18:09
  • Could be, although if I set it this way, the control displays the selected row time field, but cannot edit it. While when I bind to Value it does not even display it, which is more like what you described in the post. – Ivan Stoev Sep 11 '16 at 18:18
  • Nope Ivan, both Text and Value didn't load or saved. Tried to set bind to both Text and Value but once I enter and Update field I get stucked (focus) on that field only. – Henry Sep 11 '16 at 19:10
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/123119/discussion-between-henry-and-ivan-stoev). – Henry Sep 11 '16 at 19:38
  • 1
    Take a look at https://dotnetfiddle.net/qXEcC2 Create a new Windows Forms project and copy/paste the whole content of the fiddle in the Program.cs (replace everything inside). Then run it and let me know if it works. – Ivan Stoev Sep 11 '16 at 20:34
  • Hi Ivan, Thank you for the reply, I tried both .NETfiddle you sent on a new project. Yes it displayed the time properly, and I already tested it on my project. However this is only 1 way binding. If i try to change the time on DateTimePicker, I got stucked on the DateTimePicker control. Even clicking close on the application is not allowed unless i changed the selection on DataGridView which reverts my changes. you can see the screen here for proof [link](http://imgur.com/a/ieLup) :) – Henry Sep 11 '16 at 21:13
  • 1
    I see, thank you:) The difference with my tests is AM/PM designator - I don't have such (using 24 hour clock) and couldn't let it show it, even setting en-US culture at the beginning. Anyway, I think you should consider [TriTinMn](http://stackoverflow.com/users/2592875/tntinmn) answer, sounds quite reasonable and works in my environment. – Ivan Stoev Sep 12 '16 at 07:55
  • Hi Ivan, Thank you for the help, I will try his solution instead bro.. thank you very much again :) :) :) – Henry Sep 13 '16 at 12:22
  • 1
    You are welcome bro :) I've upvoted and tested his solution and it worked for me, so hope you'll have no problems applying it to your code. – Ivan Stoev Sep 13 '16 at 12:29