When you drop a WCF RIA service data source in the visual studio 2010 Beta 2, you will see that it generates for you a load button and assign it an event handler that call Load on the ria data source.
I don’t know for you but I find easier to use a TriggerAction than having to write the same code again and again.
In this post, I will discuss some TriggerAction that I have implemented and helps me write RIA application faster.
LoadAction
Loading data using a data source in RIA services is very simple. You only have to call Load. Why not ease that by making it available in Microsoft Expression Blend 3 using a TriggerAction.
Here is the implementation of the LoadAction that targets a DomainDataSource.
public class LoadAction : TargetedTriggerAction<DomainDataSource>
{
protected override void Invoke(object parameter)
{
var target = Target;
if (target != null && !target.IsLoadingData)
target.Load();
}
}
Wow! That was easy. 3 lines of code and we have our first action. Have a try in Blend and you will see that it really helps.
SubmitChangesAction
Submit data is also very simple. Here is how to do it using a TriggerAction:
public class SubmitChangesAction : TargetedTriggerAction<DomainDataSource>
{
protected override void Invoke(object parameter)
{
var target = Target;
if (target != null)
target.SubmitChanges();
}
}
NavigateAction
Ok, this one is a bit harder to implement but will helps you. To navigate in Silverlight, we need an instance of the NavigationService and call the Navigate method. Again, this can be simplified.
Create a TriggerAction to be attached to the Page since this is where we can have an instance of the NavigationService. We will add a property called PageUri which is the page to navigate to when the action is called:
public class NavigateAction : TriggerAction<Page>
{
#region PageUri DependencyProperty
public string PageUri
{
get { return (string)GetValue(PageUriProperty); }
set { SetValue(PageUriProperty, value); }
}
public static readonly DependencyProperty PageUriProperty = DependencyProperty.Register
(
"PageUri",
typeof(string),
typeof(NavigateAction),
new PropertyMetadata(null)
);
}
protected override void Invoke(object parameter)
{
var pageUri = PageUri;
if (string.IsNullOrEmtpy(pageUri))
return;
var page = AssociatedObject;
var uri = new Uri(pageUri, UriKind.RelativeOrAbsolute);
var service = page.NavigationService;
if (service != null)
service.Navigate(uri);
}
NavigateAction with QueryString parameters
Good, we have a working NavigateAction. I think we can do much better. How about support for passing parameters in the query string. Here is the new implementation:
[ContentProperty("Parameters")]
public sealed class NavigateAction : TriggerAction<Page>
{
public NavigateAction()
{
Parameters = new ObservableCollection<NavigateActionParameter>();
}
#region Methods
private Uri CreateUri()
{
var s = PageUri;
if (string.IsNullOrEmpty(s))
return null;
var c = s.Contains("?") ? '&' : '?';
for (var i = 0; i < Parameters.Count; i++)
{
var parameter = Parameters[i];
if (parameter == null)
continue;
var value = parameter.Value;
if (value == null)
continue;
s += c + parameter.ParameterName + '=' + Uri.EscapeDataString(value);
c = '&';
}
return new Uri(s, UriKind.RelativeOrAbsolute);
}
protected override void Invoke(object parameter)
{
var page = AssociatedObject;
var uri = CreateUri();
var service = page.NavigationService;
if (uri != null && service != null)
service.Navigate(uri);
}
#endregion
#region Properties
#region PageUri DependencyProperty
public string PageUri
{
get { return (string)GetValue(PageUriProperty); }
set { SetValue(PageUriProperty, value); }
}
public static readonly DependencyProperty PageUriProperty = DependencyProperty.Register
(
"PageUri",
typeof(string),
typeof(NavigateAction),
new PropertyMetadata(null)
);
#endregion
public ObservableCollection<NavigateActionParameter> Parameters { get; private set; }
#endregion
}
public sealed class NavigateActionParameter : DependencyObject
{
#region Properties
public string ParameterName { get; set; }
#region Value DependencyProperty
public string Value
{
get { return (string)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register
(
"Value",
typeof(string),
typeof(NavigateActionParameter),
new PropertyMetadata(null)
);
#endregion
#endregion
}
You can now use the NavigateAction and add parameters in the Query String in Blend without using code. Here is a sample
<l:NavigateAction PageUri="/BacklogItemView?Action=Update">
<l:NavigateActionParameter ParameterName="Id" Value="{Binding Path=SelectedItem.Id, ElementName=dataGrid1}"/>
</l:NavigateAction>
This will pass a parameter named Id in the Query String.
Happy programming!