Introduction
My current project is a LightSwitch SilverLight client that works on some rather large datasets. For certain screens in this application it’s desirable to set the query as non-autoexecutable because most users would want to fill in multiple filter fields before invoking the time consuming query.
However, when setting a query as non-autoexecutable you also lose some functionalities in the Silverlight client:
- Sorting & Paging in the LightSwitch SilverLight grid doesn’t work.
- When pressing the Enter key on one of the Filter fields, the query should be executed. (UI Guideline)
Sorting & Paging in the LightSwitch SilverLight grid doesn’t work
This is a known issue since the V1 beta. You can discuss about it being a bug in LightSwitch but the LightSwitch team says this is the correct behavior.
Luckily, Justin Anderson gave an easy solution for this in the following thread:
When pressing the Enter key on one of the Filter fields, the query should be executed.
This can easily be solved by using the KeyUp event of the UIElement. You can add this on every filter field, but i prefer to use the GetModel method of the screen to find all fields in my Filter Group control.
By doing this, you won’t miss to add the event if you would later add some new filter fields.
Extension method
Let’s DRY both solutions into one practical ScreenExtensions class
using System; using System.Net; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Ink; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; using Microsoft.LightSwitch; using Microsoft.LightSwitch.Framework.Client; using Microsoft.LightSwitch.Presentation; using Microsoft.LightSwitch.Presentation.Extensions; using Microsoft.LightSwitch.Client; using Microsoft.LightSwitch.Model; using System.Linq; using Microsoft.LightSwitch.Threading; using System.ComponentModel; namespace LightSwitchApplication { public static class ScreenExtensions { /// <summary> /// Execute an action when the EnterKeyUp event has been fired on the given control or its children controls. /// </summary> /// <param name="control">The name of the control. This can also be a group control.</param> /// <param name="callback">The action that needs to be executed.</param> public static void ExecuteActionOnEnterKeyOnChildrenOfGroupControl(this IScreenObject screen, string control, Action callback) { IContentItemDefinition itemDef = screen.Details.GetModel().GetChildItems(true) .OfType<IContentItemDefinition>() .FirstOrDefault(c => c.Name == control); foreach (IContentItemDefinition item in itemDef.ChildContentItems) { if (item.Kind == ContentItemKind.Group) ExecuteActionOnEnterKeyOnChildrenOfGroupControl(screen, item.Name, callback); else if (item.Kind == ContentItemKind.Details || item.Kind == ContentItemKind.Value) ExecuteActionOnEnterKeyUp(screen, item, callback); } } private static void ExecuteActionOnEnterKeyUp(IScreenObject screen, IContentItemDefinition item, Action callback) { screen.FindControl(item.Name).ControlAvailable += (sender, args) => { UIElement uiElement = args.Control as UIElement; uiElement.KeyUp += (sender1, args1) => { if (args1.Key == Key.Enter) { screen.Details.Dispatcher.BeginInvoke(callback); args1.Handled = true; //this also fixes the Modal Window Enter Key bug. Set to false if you want the event to bubble. } }; }; } /// <summary> /// Execute an action when Paging or Ordering occurs on the given collection. /// </summary> /// <param name="collectionProperty">The INotifyPropertyChanged property of the collection.</param> /// <param name="callback">The action that needs to be executed.</param> public static void ExecuteActionOnPagingOrSorting(this IScreenObject screen, INotifyPropertyChanged collectionProperty, Action callback) { Dispatchers.Main.Invoke(() => { collectionProperty.PropertyChanged += (sender, e) => { switch (e.PropertyName) { case "PageNumber": // Changed when current page is changed case "SortDescriptors": // Changed when sorting is changed screen.Details.Dispatcher.BeginInvoke(callback); break; } }; }); } } }
Use it in your Created method of the screen:
public partial class SearchScreen { private const string _controlFilterGroupBox = "FilterGroupBox"; partial void SearchScreen_Created() { this.ExecuteActionOnEnterKeyOnChildrenOfGroupControl(_controlFilterGroupBox, ReloadCustomers); this.ExecuteActionOnPagingOrSorting(this.Details.Properties.Customers, ReloadCustomers); } private void ReloadCustomers() { this.Customers.Refresh(); } }
Conclusion
This extension class now solves 2 issues when working with manual execution queries.
Enjoy!
