Note that there are some explanatory texts on larger screens.

plurals
  1. POStackOverflowException in Silverlight MVVM after page navigation
    text
    copied!<p>I am attempting to use MVVM Light to create a simple page for adding/editing/deleting Contacts and for users to send faxes from the other parts of the software. The MainPage has a simple header with some corporate info and two links, one to the Contacts page and the other to the Fax History page; most of the MainPage page is a navigation frame that is the target of the links, where the pages are loaded. I am using VS 2010/.NET 4.0/SL 4.0.</p> <p>The Contacts page has two datagrids, one for Search Contacts Results ('gridContacts') and the other for Selected Contacts (those contacts who will receive the fax--'gridSelected'). There's a Delete button for the user to delete the contact of the selected row in the Search grid. There's also a Send Fax button to send the fax to those contacts in the gridContacts grid.</p> <p>Problem is, if I ever select a row in the Search grid, navigate to Fax History, then come back, I get a StackOverflowException before the navigation occurs. If I navigate to the other page first, then come back, and then select a row, I'll get the exception at that point. I found that the Send Fax button also has causes the same exception when I removed the Delete button. On both buttons, I am able to work around the problem just coding everything in code-behind; obviously this is not ideal, so I want to learn to get it to work with MVVM.</p> <p>When I step through the code for the problem with the Delete button, I see that the exception occurs in the DelegateCommand that the Delete button is bound to. In the CanExecute method, the first time through, the object parameter is correctly a Contact (since the grid is bound to a List of Contacts). It fires CanExecuteChanged(this,new EventArgs()) as part of the code logic--but then comes BACK into the function, but with null as the parameter passed in. Here is where an infinite loop becomes evident: CanExecute fires in a loop and alternates between having a Contact object and null as the parameter passed in. The stack trace shows External Code between the calls to CanExecute, but that's the only method present. The infinite loop eventually causes the StackOverflowException.</p> <p>Here's the code in question:</p> <pre><code> public bool CanExecute(object parameter) //parameter alternates between Contact object and null { bool temp = _funcCanExecute(parameter); //_funcCanExecute is set to CanDelete in the DelegateCommand constructor. if (_bCanExecuteCache != temp) { _bCanExecuteCache = temp; if (CanExecuteChanged != null) { CanExecuteChanged(this, new EventArgs()); //this line somehow leads to another call into here --&gt; infinite loop } } return _bCanExecuteCache; } </code></pre> <p>The Search grid ItemSource is bound to a VM via a Locator like so: </p> <pre><code>&lt;sdk:DataGrid AutoGenerateColumns="False" x:Name="gridContacts" IsTabStop="False" Grid.Row="3" ItemsSource="{Binding Path=SearchContactsViewModel.Contacts, Mode=OneWay, Source={StaticResource Locator}}" SelectionMode="Single"&gt; </code></pre> <p>Here are the Delete button Command and CommandParameter (the overall data context is set as DataContext="{Binding Source={StaticResource Locator}, Path=SearchContactsViewModel}"):</p> <pre><code> &lt;Button x:Name="btnDelete" Style="{StaticResource ButtonStyle}" Command="{Binding Path=SearchContactsViewModel.DeleteContactCommand, Source={StaticResource Locator}}" Grid.Row="1" Grid.Column="1" CommandParameter="{Binding Path=SelectedItem, ElementName=gridContacts}" HorizontalAlignment="Right"&gt; </code></pre> <p>Here's the simplified code in the SearchContactsViewModel:</p> <pre><code> public DelegateCommand DeleteContactCommand { get; private set; } private bool CanDeleteContact(object param) { Contact c = param as Contact; if (c == null) return false; return true; } private void DeleteContact(object param) { int contactID = ((Contact)param).ID; _ServiceAgent.DeleteContact(contactID, (s, e) =&gt; { if (!CheckErrorAndResult(e.Error, e.Result, e.errMsg)) return; SearchContacts(); MessageBox.Show("Delete successful."); }); } </code></pre> <p>Here is the line of code that wires up the command in the VM:</p> <pre><code>DeleteContactCommand = new DelegateCommand(DeleteContact, CanDeleteContact); </code></pre> <p>BUT, if I replace CanDeleteContact with "(x) => true" for testing, I do NOT get the problem.</p> <p>Please let me know if I can provide more information. I'm trying to figure out the problem with the Delete button first and hopefully apply the same solution to the Send Fax button.</p> <p>Thanks, J</p> <p>***UPDATE 9/6/2011: I have noticed that in Silverlight navigation, a new instance of the page is created each time. So would that account for why this problem only happens after navigation? And why the values handled in what I thought was an infinite loop are alternating between null and non-null values? Like maybe the old page now has null, but the new page is being shown and is correct, but both are tied to the same static VM object. Just shooting in the dark here.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload