When changes are successfully submitted and you have paging enabled, it’s quite possible that some of the entities that have been edited now belong to a different page.  Say for instance you are viewing employees ordered by last name, and you edit one of the employees to change their last name, moving them from Jones to Adams.  After submitting changes, what should happen?  Should Adams continue to show up on the 6th page, or should the data be refreshed to place everyone where they belong?

A few months ago, we made the decision to invoke a fresh load after SubmitChanges() completes successfully.  This will refresh your client view to reflect what has changed on the server, putting people on the right page.  But here we are at PDC, releasing a new build of RIA Services with this in place, and I’m somewhat regretting that design decision.  I was chatting with my manager about this, and as he said, “That’s a very heavy-handed solution to an uncommon problem.”  He’s right.  We are filing a bug to try to remove this automatic load after submitting changes.  The solution is so aggressive in fact, that the load occurs regardless of whether or not you’re using paging—we always do the load after every SubmitChanges() call succeeds.

Why is this Behavior so Annoying?

Aside from the fact that DomainDataSource is performing a load when you might not want it to, this behavior gets especially annoying when paging is enabled.  Ironic, I know.  The problem is that the load that is invoked will actually return the view to the first page.  So if the end user was editing records on the 5th page, and hits the button to submit changes, they will find themselves performing a “back flip” to page 1.

Disabling the Behavior

Here’s a quick and easy way to prevent this post-submit load from happening:

  1. In the SubmittedChanges event handler, check to see if the the submission was successful (!e.Cancelled && !e.HasError).  If it was successful, set a private field for _justSubmitted = true.
  2. In the LoadingData event handler, check to see if _justSubmitted is true, and if so, set e.Cancel = true, and _justSubmitted to false.

Of course, you can also derive from DomainDataSource and add this logic, but this is Silverlight, and we have Attached Behaviors!

So here we have DomainDataSourceBehaviors.LoadAfterSubmit:

using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
 
namespace QuickSilverlight.Behaviors
{
    public class DomainDataSourceBehaviors
    {
        public static readonly DependencyProperty LoadAfterSubmitProperty =
            DependencyProperty.RegisterAttached("LoadAfterSubmit", typeof(bool),
                typeof(DomainDataSourceBehaviors), new PropertyMetadata(false));
 
        private static HashSet<DomainDataSource> _submitted = new HashSet<DomainDataSource>();
 
        public static bool GetLoadAfterSubmit(DomainDataSource dds)
        {
            return (bool)dds.GetValue(LoadAfterSubmitProperty);
        }
 
        public static void SetLoadAfterSubmit(DomainDataSource dds, bool value)
        {
            dds.SetValue(LoadAfterSubmitProperty, value);
 
            if (dds != null)
            {
                if (!value)
                {
                    dds.SubmittedChanges += SubmittedChanges;
                    dds.LoadingData += LoadingData;
                }
                else
                {
                    dds.SubmittedChanges -= SubmittedChanges;
                    dds.LoadingData -= LoadingData;
                }
            }
        }
 
        private static void SubmittedChanges(object sender, SubmittedChangesEventArgs e)
        {
            if (!e.Cancelled && !e.HasError)
            {
                _submitted.Add((DomainDataSource)sender);
            }
        }
 
        private static void LoadingData(object sender, LoadingDataEventArgs e)
        {
            DomainDataSource dds = sender as DomainDataSource;
 
            if (_submitted.Contains(dds))
            {
                e.Cancel = true;
                _submitted.Remove(dds);
            }
        }
    }
}

 

Here’s how it’s used:

<riaControls:DomainDataSource QueryName=”GetCustomers
        qs:DomainDataSourceBehaviors.LoadAfterSubmit=”false>
    ...
</riaControls:DomainDataSource>

 

By applying this attached behavior, your DomainDataSource will no longer do “back flips” to the first page when changes are submitted.  Hope this helps!

Technorati Tags: ,