7

I'm building a WPF application that uses simple MVVM architecture and EF.

I'm seeing a weird issue where if I try to set a datetime property, I get a System.StackOverflowException. If I don't set the datetime property, I don't get the exception.

Binding:

   <DatePicker Style="{StaticResource Dp}" 
               Grid.Column="1" 
               SelectedDate="{Binding Date, UpdateSourceTrigger=PropertyChanged}" />

Public property:

public DateTime Date
{
    get
    {
        return _criticalDate.Date;
    }
    set
    {
        if (_criticalDate != null && value != null && _criticalDate.Date == value)
            return;
        _criticalDate.Date = value;
        OnPropertyChanged("Date");
    }
}

Trying to step through it with a debugger doesn't seem to work. I've looked at everything trying to see what is going on... any hints on what might be causing this?

This is the definition for the CriticalDate class,

public partial class CriticalDate
{
    public int ID { get; set; }
    public System.DateTime Date { get; set; }
    public string CriticalReason { get; set; }
    public int FileID { get; set; }
}

The _criticalDate field is a private instance of the CriticalDate class. CriticalDate is a class created by EF from my DB schema. It isn't itself a DateTime.

FINAL UPDATE

I still don't know what was wrong... I tore the offending section out (including the binding) and rewrote it from scratch. No clue what I did differently, but it works now. I think it was something to do with how an itemscontrol was set up... if I had more time (stupid deadlines) I'd go back to see what it was, but for now it's a mystery.

Thanks for sharing in my confusion, if only ever so briefly.

Chronicide
  • 1,112
  • 1
  • 9
  • 32
  • 12
    Add `if (_criticalDate == this) throw new Exception("Bug");` – Hans Passant Jan 16 '14 at 20:25
  • StackOverflowException on which function? BTW here I would expect a NullReferenceException when _criticalDate is null... – Adriano Repetti Jan 16 '14 at 20:25
  • I suspect `OnPropertyChanged("Date");` might be the culprit here. – Moo-Juice Jan 16 '14 at 20:26
  • I suspect `NullReferenceException` on the `get` because `_criticalDate` is `null`. – gleng Jan 16 '14 at 20:26
  • I put breakpoints all over, and I didn't notice any recursion within this class... – Chronicide Jan 16 '14 at 20:26
  • @HansPassant nice way of looking for the recursion! – Evan L Jan 16 '14 at 20:27
  • I think Hans is right, until _criticalDate == this he'll be free from a long list of (possible) exceptions! :) – Adriano Repetti Jan 16 '14 at 20:27
  • 2
    What is the type of `_criticalDate`? Can you post the implementation? – Markus Jan 16 '14 at 20:28
  • Also... _criticalDate is a business object, not another datetime – Chronicide Jan 16 '14 at 20:29
  • @rae1n Where? I still can't figure this out (I've been at this for 3 hours already) – Chronicide Jan 16 '14 at 20:38
  • What's the binding type for the `SelectedDate` property? – rae1 Jan 16 '14 at 20:41
  • Do you mean mode? it's TwoWay... but it still doesn't feel like a recursion issue.. breakpoints in my class are only reached once, not repeatedly – Chronicide Jan 16 '14 at 20:44
  • Where are you placing the breakpoint? Which line? – rae1 Jan 16 '14 at 20:49
  • I put breakpoints in every get/set, constructor and method in the whole class... none of them were called more than once. – Chronicide Jan 16 '14 at 20:59
  • 1
    You might have to look at the stack after the exception is thrown (run the application on DEBUG for this). The methods' names should give some clue... – rae1 Jan 16 '14 at 21:05
  • I used to get this exception when I enabled DataBinding debugging, but it disappeared when I disabled it. Could you try that? – Boluc Papuccuoglu Jan 16 '14 at 21:29
  • 1
    `If I don't set the datetime property, I don't get the exception.` - where are you setting it?? – YK1 Jan 16 '14 at 21:32
  • Possibly related to the open bug [StackOverflowException in WPF DatePicker with non en-US date format](https://connect.microsoft.com/VisualStudio/feedback/details/785944/stackoverflowexception-in-wpf-datepicker-with-non-en-us-date-format) which has no fix planned due to low impact. Where I seemed to encounter it was in code that had the `Text` and `DisplayDate` properties bound in XAML in addition to `SelectedDate`. On switching to to just binding the `SelectedDate`, everything then seemed to work as expected (no exceptions, display date updated fine). – Tone Jun 16 '17 at 21:27

3 Answers3

0

Try removing the OnPropertyChanged("Date");, or change the binding mode to OneWayToSource.

From the documentation of UpdateSourceTrigger.

Bindings that are TwoWay or OneWayToSource listen for changes in the target property and propagate them back to the source. This is known as updating the source. Usually, these updates happen whenever the target property changes. This is fine for check boxes and other simple controls, but it is usually not appropriate for text fields. Updating after every keystroke can diminish performance and it denies the user the usual opportunity to backspace and fix typing errors before committing to the new value. Therefore, the default UpdateSourceTrigger value of the Text property is LostFocus and not PropertyChanged.

I believe that OnPropertyChanged("Date"); on the Date_set method is updating the UI, which is in turn calling the Date_set method again, which completes the cycle and causes the recursion.

rae1
  • 6,066
  • 4
  • 27
  • 48
  • Oddly enough, I get this error even when the setter is completely empty. No OnPropertyChange, no setting private properties, but I still get the error. – Chronicide Jan 16 '14 at 21:11
0

Edit: The following is useless since the debugger doesn't display a call stack for stack overflows. Instead, take a look at How to debug a stackoverflowexception in .NET


Set the Visual Studio debugger to break on StackOverflowExceptions and examine the callstack.

Ctrl+Alt+E

or

Debug->Exceptions...

Click Find and type StackOverflow then check the box in the Thrown column.

You will probably have hundreds of recursive calls in the same method or set of methods.

If the exception occurs inside a library, you might need to disable "Just My Code"

Community
  • 1
  • 1
dss539
  • 6,804
  • 2
  • 34
  • 64
  • You can't see the call stack with stack overflow exceptions. You get this lovely message saying 'cannot evaluate, because you're in stack overflow state.' That's why I can't figure this out.... no idea what's going on. – Chronicide Jan 16 '14 at 21:10
  • @Chronicide Doh, you're right. I forgot about that. It looks like there are other ways to debug it though. http://stackoverflow.com/questions/4733878/how-to-debug-a-stackoverflowexception-in-net – dss539 Jan 16 '14 at 21:14
0

Make sure you are not updating your date when you don't need to, and break the feed back loop in your binding. I typically put this check around my setters:

public DateTime Date
{
    get
    {
        return _criticalDate.Date;
    }
    set
    {
        if (_criticalDate.Date != value)
        {
            if (_criticalDate != null && value != null && _criticalDate.Date == value)
               return;
            _criticalDate.Date = value;
            OnPropertyChanged("Date");
        }
    }
}
ansible
  • 3,569
  • 2
  • 18
  • 29
  • I'm already doing this... the return is reached if the dates match, so the setting on onpropertychanged won't be run if the do. Same as your suggestion, just a bit backwards. – Chronicide Jan 16 '14 at 21:24
  • @Chronicide - Hmm, FYI - if _criticalDate == null, you'll crash, so that check is extra. Also if value==null and _criticalDate.Date==null, your check won't work. What happens if you try set a break point? – ansible Jan 16 '14 at 21:30
  • And if `value` is a `DateTime` it can never be `null`. – rae1 Jan 16 '14 at 22:45