A couple of highly useful memory management references from RedGate
Tag: SilverLight
-

Silverlight Deferred / Delayed Selected Date Picker
When implementing a date picker that is used to fetch some ‘details’ based on the selected date, the chances are that you don’t want to begin fetching the ‘details’ immediately.
If you did, and made a rapid change to the SelectedDate (maybe holding down an arrow key), the asynchronous fetch will be repeated a large number of times.
To prevent this, implement a deferral on the selected date change, for example:
public class DeferredDP : DatePicker { public DeferredDP() { this.DefaultStyleKey = typeof(DatePicker); base.SelectedDateChanged += new EventHandler(DeferredDP_SelectedDateChanged); } DispatcherTimer _timer; void DeferredDP_SelectedDateChanged(object sender, SelectionChangedEventArgs e) { /// if there is an instance of the timer already running stop it. if (_timer != null) { _timer.Stop(); _timer = null; } /// only trigger the selection changed event when the date has been changed if (e.AddedItems.Count == 1 && e.AddedItems[0] is DateTime) { if (SelectionDelay.HasValue) { /// if the timer delay has been set, delay the setting of the value _timer = new DispatcherTimer(); _timer.Interval = new TimeSpan(0,0,0,0,SelectionDelay.Value); _timer.Tick += (s1, e1) => { SetValue(SelectedDateDeferredProperty, (DateTime)e.AddedItems[0]); if (_timer != null) { _timer.Stop(); _timer = null; } }; _timer.Start(); } else { // if the timer delay is not set, set the property immediately. SetValue(SelectedDateDeferredProperty, (DateTime)e.AddedItems[0]); } } } /// /// Milliseconds delay before the selected date value is updated. /// public int? SelectionDelay { get { return (int?)GetValue(SelectionDelayProperty); } set { SetValue(SelectionDelayProperty, value); } } public static readonly DependencyProperty SelectionDelayProperty = DependencyProperty.Register("SelectionDelay", typeof(int?), typeof(DeferredDP), new PropertyMetadata(null)); public DateTime? SelectedDateDeferred { get { return (DateTime?)GetValue(SelectedDateDeferredProperty); } set { SetValue(SelectedDateDeferredProperty, value); } } public static readonly DependencyProperty SelectedDateDeferredProperty = DependencyProperty.Register("SelectedDateDeferred", typeof(DateTime?), typeof(DeferredDP), new PropertyMetadata(null, SelectedDateDeferredChanged)); public static void SelectedDateDeferredChanged(DependencyObject d, DependencyPropertyChangedEventArgs args) { DeferredDP instance = d as DeferredDP; if (instance.SelectedDateDeferred != instance.SelectedDateDeferred) { instance.SelectedDateDeferred = instance.SelectedDateDeferred; } } } -

MSDTC
We had some really strange problems getting MSDTC to work recently, specifically upgrading to VS2010 and SL4. Our developer environments are pointing to networked database servers and during this particular use-case the development workstation is running a both the hosted Silverlight Client and the Business Logic (API) served through a WCF service (both in Cassini). The API is performing the transactional logic.
So, working through the bugs and error messages that we got;
The first error requires MSDTC to be started (which is wasn’t by default):
The transaction manager has disabled its support for remote/network transactions. Both the WCF Server (in our case the developer workstation) and the Database Server have to have MSDTC running. Start MSDTC using the command line: NET START MSDTC
YMMV, but on Win7 the default properties for DTC also had to be updated. From Component Services MMC, navigate to Computers | My Computer | Distributed Transaction Coordinator | Local DTC. Right click + Properties and set as follows:

Next error then relates to the default firewall setting:
The MSDTC transaction manager was unable to pull the transaction from the source transaction manager due to communication problems. Possible causes are: a firewall is present and it doesn’t have an exception for the MSDTC process, the two machines cannot find each other by their NetBIOS names, or the support for network transactions is not enabled for one of the two transaction managers. Sometimes we didn’t get this exception, and got a timeout instead and the failed transaction could be seen in the outstanding transactions list.
To resolve this we updated the Windows Firewall to add an inbound and outbound tunnel for %SystemRoot%\System32\msdtc.exe
All seems to OK … for now… :S
-
Silverlight Tab Stops – IsTabStop
Just found a tricky little quirk with TabStop that caused a fair bit of confusion. It turns out that the default implementation of ContentControl overrides Control, so implements the IsTabStop property, and defaults that value to true.
ContentControl is implemented by the delightful BusyIndicator, so if you have used a BusyIndicator within the scope of a series of input controls you’ll see the Invisible Tab Stop behaviour.
HINT: Using Silverlight Spy shows us where the offending property lies. You’ll need to re-template that to set the IsTabStop property to false.
-
Telerik RadGridView Exception when trying to use the Filter Columns feature
Was getting an unhandled Silverlight exception when trying to apply column filters in the Telerik RagGridView component. This was caused by a missing reference to the Telerik.Windows.Controls.Input.dll which is probably being used by the filter UI elements.
-
Silverlight Commands – Data grid row selected
following on from http://thoughtjelly.blogspot.com/2009/09/silverlight-prism-commands-textchanged.html and in response to John Papa’s PDC talk http://johnpapa.net/silverlight/mvvm-and-prism-demo-for-pdc09-silverlight-session. Another highly useful command behaviour is for DataGridRowSelected.
This also gets over the issues described here and here. The code (as written by John Papa) is:public class DataGridRowSelectedCommandBehavior : CommandBehaviorBase
{
public DataGridRowSelectedCommandBehavior(DataGrid selectableObject)
: base(selectableObject)
{
selectableObject.SelectionChanged += OnSelectionChanged;
}
private void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
this.CommandParameter = this.TargetObject.SelectedItem;
ExecuteCommand();
}
}And
public static class DataGridRowSelected
{
private static readonly DependencyProperty DataGridRowSelectedCommandBehaviorProperty = DependencyProperty.RegisterAttached(
"SelectedCommandBehavior",
typeof(DataGridRowSelectedCommandBehavior),
typeof(DataGridRowSelected),
null);
public static readonly DependencyProperty CommandProperty = DependencyProperty.RegisterAttached(
"Command",
typeof(ICommand),
typeof(DataGridRowSelected),
new PropertyMetadata(OnSetCommandCallback));
public static void SetCommand(DataGrid dataGrid, ICommand command)
{
dataGrid.SetValue(CommandProperty, command);
}
public static ICommand GetCommand(DataGrid dataGrid)
{
return dataGrid.GetValue(CommandProperty) as ICommand;
}
private static void OnSetCommandCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
{
var dataGrid = dependencyObject as DataGrid;
if (dataGrid != null)
GetOrCreateBehavior(dataGrid).Command = e.NewValue as ICommand;
}
private static DataGridRowSelectedCommandBehavior GetOrCreateBehavior(DataGrid dataGrid)
{
var behavior = dataGrid.GetValue(DataGridRowSelectedCommandBehaviorProperty) as DataGridRowSelectedCommandBehavior;
if (behavior == null)
{
behavior = new DataGridRowSelectedCommandBehavior(dataGrid);
dataGrid.SetValue(DataGridRowSelectedCommandBehaviorProperty, behavior);
}
return behavior;
}
}
