A Runnable Scheduler for Reactive Extensions
Task And Cancellation
Foreword
One scenario tought that is missing love is Cancellation. Here is a sample code that does not support cancellation :
Task running 1
Task running 2
Key Press!
Task running 3
Task running 4
...
Cancelling a Task with a CancellationToken
Task running 1
Task running 2
Key Press!
Removing the CancellationToken noise
static void Main(string[] args)
Diving deep into the bits...
Create a custom Task Factory method
Add a Cancel method on the Task
Wait with ambient cancellation
Final Words
Client Databases for Silverlight
When comes the time to use Silverlight out of browser functionality, we may have to face the fact that Silverlight might be used without an internet connection. In this particular case, the application must implement a local cache.
I have found some very interesting database solution available for Silverlight.
siaqodb (in beta when this post was published)
This database is using LINQ natively to retrieve the data which is stored in the isolated storage on the client machine.
var p = new Product { Name = "Pencil", Price = 0.25 };
db.StoreObject(product);
var query = from Product p in db
where p.Name == "Pencil"
select p;
Silverlight Database (in beta when this post was published)
Again, this database is using the isolated storage to persist locally the offline data.
var db = Database.CreateDatabase("test");
db.CreateTable<Person>();
var person = new Person{ FirstName = "John", LastName = "Doe" };
db.Table<Person>().Add(person);
var q = from p in db.Table<Person>()
where p.LastName == "Doe"
select p;
Others
db4o : They are working on a Silverlight port.
EffiProzSL : A port of the EffiProz database.
Perst : A port from Java.
Experimentations
Google gears and silverlight
C#-SQLite running in Silverlight
Happy new year!
WCF RIA Services without code using a TriggerAction
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!