Universal App with Lex.DB 26 June 2014 Diederik-Krols Universal Windows Apps, Windows Phone, WinRT This article shows how to create a Universal Windows App that stores its local data in Lex.DB. This is a lightweight, developer-friendly in-process database engine, completely written in C#. For an introduction to building Store Apps on top of Lex.DB, please check this article of mine. For a more advanced dive into performance tuning, check this one – and make sure you don’t skip the valuable comments from Lex Lavnikov, the author of Lex.DB, at the end. Lex.DB can be used on .NET 4+, Silverlight 5+, Windows Phone 8+, WinRT 8+, and Xamarin. Recently this alternative for SQLite was upgraded to support Universal Windows Apps. I created a straightforward sample app, based on the Universal App with SQLite blog post by Nicolò Carandini. I added a tiny MVVM Framework with BindableBase and RelayCommand just for fun. The sample app manages a list of Person instances. This is the Person class, as simple as can be:public class Person { public int Id { get; set; } public string Name { get; set; } public string Degree { get; set; } public string Occupation { get; set; } } .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } The sample app comes with commands to add a Person, delete the selected Person, and reset the database to its default content. Here’s how it looks like in the emulator and the simulator: You just need to add the Lex.DB Nuget package in your solution: Each of the platform-specific projects will reference its own Lex.DB dll. That’s a lot simpler than SQLite, where you need to install an SDK, reference the C++ runtime *and* integrate some extra source code into your projects. The following screenshots illustrate the impact of both databases to your Visual Studio solution, with SQLite on the left, and Lex.DB on the right: Here’s how the data access layer creates a reference to the database – in a static constructor:private static DbInstance db; static Dal() { // Create database db = new DbInstance("Storage", ApplicationData.Current.RoamingFolder); // Define table mapping // * 1st parameter is primary key // * 2nd parameter is autoGen e.g. auto-increment db.Map<Person>().Automap(p => p.Id, true); // Initialize database db.Initialize(); } The following method returns the content of the Person table:public static IEnumerable<Person> GetPeople() { return db.Table<Person>(); } I defined two methods to insert/update Person instances: one for a single instance (it returns the generated primary key) and another one to save a list (in one transaction – read the already mentioned perfomance tuning article for more details):public static int SavePerson(Person person) { db.Table<Person>().Save(person); return person.Id; } public static Task SavePeople(IEnumerable<Person> people) { return db.Table<Person>().SaveAsync(people); } Here’s how to give your database some initial (default) content:public static Task ResetPeople() { // Clear db.Purge<Person>(); // Repopulate return Dal.SavePeople( new List<Person>() { new Person() { Name="Leonard Leakey Hofstadter", Degree="Ph.D.", Occupation="Experimental physicist"}, new Person() {Name="Sheldon Lee Cooper", Degree="Ph.D.", Occupation="Theoretical physicist"}, new Person() {Name="Howard Joel Wolowitz", Degree="M.Eng.", Occupation="Aerospace engineer"}, new Person() {Name="Rajesh Ramayan Koothrappali", Degree="Ph.D.", Occupation="Astrophysicist"} }); } .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } For the sake of completeness, here’s the delete method:public static Task DeletePeople(IEnumerable<Person> people) { return db.Table<Person>().DeleteAsync(people); } .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } Here’s the full source code of the sample app, it was written in Visual Studio 2013 Update 2: U2UC.WinUni.LexDBSample.zip (1.2MB) Enjoy! XAML Brewer
A Marching Ants Animation for Universal Windows Apps 17 June 2014 Diederik-Krols Universal Windows Apps, Windows Phone, WinRT In a lot of apps we need to draw lines on some kind of map to display a route. If you want such line to also indicate the driving direction and speed, then you could apply the Marching Ants Effect, where you represent the route as a dotted or dashed line and let the dashes walk slowly sideways and up and down. In the XAML world, this is remarkably easy. All you need to do is apply a dash pattern to the line (or PolyLine, or any other Shape) through the Shape.StrokeDashArray property and then animate its Shape.StrokeDashOffset. Here’s an example of the effect – since a screenshot would be rather silly, I created a movie where you see the marching ants (well, in this case they might be orcs) in the attached sample project: MarchingAnts.wmv (1.4MB) As mentioned, you have to first make the line look as an ants line, so use the appropriate values for the Shape.StrokeDashCap and Shape.StrokeLineJoin properties:Polyline line = new Polyline(); // Add Points // line.Points.Add(new Point(...)); line.Stroke = new SolidColorBrush(Colors.OrangeRed); line.StrokeThickness = 18; line.StrokeDashArray = new DoubleCollection() { 4, 2 }; line.StrokeDashCap = PenLineCap.Round; line.StrokeLineJoin = PenLineJoin.Round; .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } For the animation I use a Storyboard with nothing but a DoubleAnimation on the Shape.StrokeDashOffset property. That offset moves from 0 to the total length of the dash pattern, which can be conveniently calculated with a LINQ Sum operator. I implemented it as an extension method to the Shape class. It only takes the duration of the animation as a parameter:public static void ApplyMarchingAntsAnimation(this Shape shape, TimeSpan duration) { Storyboard storyboard = new Storyboard(); DoubleAnimation doubleAnimation = new DoubleAnimation(); doubleAnimation.From = 0.0; doubleAnimation.To = -shape.StrokeDashArray.Sum(); doubleAnimation.Duration = new Duration(duration); doubleAnimation.AutoReverse = false; doubleAnimation.RepeatBehavior = RepeatBehavior.Forever; doubleAnimation.EnableDependentAnimation = true; // Don't forget storyboard.Children.Add(doubleAnimation); Storyboard.SetTarget(doubleAnimation, shape); Storyboard.SetTargetProperty(doubleAnimation, "StrokeDashOffset"); storyboard.Begin(); } .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } You can apply the animation to the Stroke of any Shape with the following one-liner:line.ApplyMarchingAntsAnimation(TimeSpan.FromSeconds(1)); .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } Everything is implemented in the shared part of a universal app, so it works on the desktop, the tablet and the phone too. This is just a screenshot, but I assure you “it’s alive…”: Here’s the whole source, it was written in Visual Studio 2013 Update 2: U2UC.WinUni.MarchingAnts.zip (555.9KB) Enjoy! XAML Brewer
A Show-All-Or-Nothing Behavior for Windows Universal Apps 10 June 2014 Diederik-Krols Universal Windows Apps Universal apps need to have a responsive UI that adapts to hugely differing form factors. This article describes how to build a Border control that hides its content when it’s too large to be fully displayed on the screen. It is implemented as a behavior, since –unlike in WPF- all native WinRT and Windows Phone controls are sealed. Originally, I had built a HideOnTrimTextBlock: a TextBlock that displays nothing if the text becomes too wide to display. The calculation was triggered when the TextBlock’s size changed. I soon discovered two things: the SizeChanged event for a TextBlock is often swallowed by its parent, so you have to walk up the visual tree to hook event handlers there, and the code used only members of FrameworkElement, so it was applicable to more than just TextBlock controls. So I turned the HideOnTrimTextBlock into a ShowAllOrNothingBorder. To detect whether the content of an element is too wide to be displayed, we compare its DesiredSize (don’t forget to Measure first) with its rendered ActualWidth. I implemented this test as an extension method:public static class FrameworkElementExtensions { /// <summary> /// Returns whether or not the content of the element is too wide to be displayed entirely. /// </summary> public static bool IsContentTooWide(this FrameworkElement element) { element.Measure(new Size(double.MaxValue, double.MaxValue)); return element.DesiredSize.Width > (element.ActualWidth + 1); } } I only check the Width here, feel free to bring the Height into the equation. The ShowAllOrNothing Universal Behavior implements IBehavior and applies to any Border. In the SizeChanged we verify whether the content is too wide or not, and adjust the Opacity of the border's Child (alternatively you could play on the Visibility). Here’s the whole behavior:/// <summary> /// A behavior that makes a Border's content disappear when it doesn't entirely fit the screen. /// </summary> public class ShowAllOrNothingBehavior : DependencyObject, IBehavior { private Border border; public DependencyObject AssociatedObject { get { return this.border; } } public void Attach(DependencyObject associatedObject) { if (associatedObject is Border) { this.border = associatedObject as Border; this.border.SizeChanged += this.Border_SizeChanged; } else { throw new Exception("ShowAllOrNothingBehavior Behavior only applies to Border."); }; } private void Border_SizeChanged(object sender, SizeChangedEventArgs e) { if (this.border.IsContentTooWide()) { this.border.Child.Opacity = 0; } else { this.border.Child.Opacity = 1; } } public void Detach() { if (this.border != null) { this.border.SizeChanged -= this.Border_SizeChanged; } } } Here’s how to attach the behavior in XAML:<Page ... xmlns:interactivity="using:Microsoft.Xaml.Interactivity" xmlns:behaviors="using:U2UC.WinUni.Behaviors" ...> <Border> <interactivity:Interaction.Behaviors> <behaviors:ShowAllOrNothingBehavior /> </interactivity:Interaction.Behaviors> <TextBlock Text="I'm sorry, Dave. I'm afraid I can't do that." /> </Border> Here’s a screen shot of the attached sample app. It illustrates a number of text block responsiveness options, such as word wrapping, character trimming, word trimming, and shrinking. The ShowAllOrNothing behavior is attached to the last one: The slider at the bottom of the screen determines the width of the text blocks’ parent. When you slide it to the left you’ll see the last text immediately disappear when it’s touched by the red line: In some use cases it makes sense to entirely hide a control if it doesn’t fit the screen. In the following screen shot, I believe that none of the text blocks actually produce any useful output: Since it’s a Universal app, it’s also supposed to work on the phone: All the code is sitting in the Shared project of a Universal App solution. The Windows 8.1 and Windows Phone 8.1 apps just need to reference their own platform-specific Behaviors SDK: .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } You may want to implement this behavior in a Portable Class Library instead. In that case I suggest you first read this article by Joost van Schaik. For the sake of completeness, here’s how this code would look like in WPF. Since the control classes are not sealed, we can put everything in a Border subclass:// Wpf Control. namespace WpfApplication { using System.Windows; using System.Windows.Controls; /// <summary> /// A Border that makes its content disappear when it doesn't entirely fit the screen. /// </summary> public class ShowAllOrNothingBorder : Border { /// <summary> /// Initializes a new instance of the <see cref="ShowAllOrNothingBorder"/> class. /// </summary> public ShowAllOrNothingBorder() { this.SizeChanged += ShowAllOrNothingBorder_SizeChanged; } /// <summary> /// Determines whether content is too wide. /// </summary> public bool IsContentTooWide() { this.Measure(new Size(double.MaxValue, double.MaxValue)); return this.DesiredSize.Width > (this.ActualWidth + 1); } private void ShowAllOrNothingBorder_SizeChanged(object sender, SizeChangedEventArgs e) { if (IsContentTooWide()) { this.Child.Opacity = 0; } else { this.Child.Opacity = 1; } } } } .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } Here’s the full source code, it was written in Visual Studio 2013 Update 2: U2UC.WinUni.Behavior.zip (132.2KB) Enjoy! XAML Brewer
A Radial Gauge for Universal Windows Apps 14 April 2014 Diederik-Krols Universal Windows Apps This article presents a modern radial gauge Custom Control, hosted in a Portable Class Library for Universal Windows apps. Visual Studio Update 2 comes with the concept of Universal Apps that can run on Windows PC’s, tablets, phones and the XBox. For an introduction to this new breed of apps, check this crystal clear article by Jeff Prosise. I did not develop this custom control from scratch, I just migrated my own Radial Gauge for WinRT which was designed by Arturo Toledo and is available through NuGet as part of the WinRT Xaml Toolkit. Here’s how the Universal Gauge looks like in both the emulator and the simulator: I started by creating a new solution with a blank C# Universal App. The template creates three projects: a Windows Store app project, a Windows Phone project, and a so-called Shared project, that contains all common source files and assets. I didn’t want to create the custom control as a bunch of shared source files, so I added an empty Portable Class Library. Visual Studio 2013 Update 2 contains a project template for such a Universal PCL: In the class library I created a new custom control. And yes, there’s again a template for that: For more information on building customs controls from scratch, you may want to read this article of mine. It seems to apply to Universal apps too. I copied the XAML style in the Themes folder and the C# class over from the Windows Phone version of the Radial Gauge, because that’s my most recent version. I had to just (re-)adapt a couple of namespaces, and tadaa: the radial gauge custom control was operational in less than 15 minutes, with a single code base for all XAML platforms (well, almost, not sure about WPF). While playing with the source, I added a new property -TickSpacing- as suggested by Dennis Almond in a blog post comment. Thanks, Dennis! /// <summary> /// Gets or sets the tick spacing, in units. /// </summary> public int TickSpacing { get { return (int)GetValue(TickSpacingProperty); } set { SetValue(TickSpacingProperty, value); } } .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } The TickSpacing allows you to specify the distance between the ticks. I used to divide the scale in 10 zones, but now you can choose your own interval for the ticks. Look at the slider-bound gauge on the right: it’s divided in 5 zones: Here’s the updated list of configurable properties: Minimum: minimum value on the scale (double) Maximum: maximum value on the scale (double) Value: the value to represent (double) ValueStringFormat: StringFormat to apply to the displayed value (string) Unit: unit measure to display (string) TickSpacing: spacing -in value units- between ticks (int) NeedleBrush: color of the needle (Brush) TickBrush: color of the outer ticks (Brush) ScaleWidth: thickness of the scale in pixels – relative to the control’s default size (double) ScaleBrush: background color of the scale (Brush) ScaleTickBrush: color of the ticks on the scale (Brush) TrailBrush: color of the trail following the needle (Brush) ValueBrush: color of the value text (Brush) UnitBrush: color of the unit measure text (Brush) And the taxonomy: As an example, here’s Daffy’s gauge from the sample project:<controls:RadialGauge Value="60" Unit="Quacks" NeedleBrush="#FFCC2B33" ScaleBrush="Transparent" TrailBrush="Black" TickBrush="#FFFFAA00" ValueBrush="White" UnitBrush="White" ScaleTickBrush="DimGray" /> .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } And here’s the data bound gauge, featuring TickSpacing:<controls:RadialGauge Minimum="{Binding Min}" Maximum="{Binding Max}" Value="{Binding Value, Mode=TwoWay}" TickSpacing="100" Unit="Bindings" NeedleBrush="White" ScaleBrush="LightGray" TrailBrush="OrangeRed" TickBrush="LightGray" ValueBrush="White" UnitBrush="White" ScaleTickBrush="Transparent" ScaleWidth="5" /> .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } Let’s come back to the Universal app. The Store app and the Phone app have something in common: they’re absolutely empty. It shouldn't come as a surprise that the ViewModel and the BindableBase classes are easily sharable, since they're simple C# classes. But the whole user interface is actually shared between the platform-specific apps: it's Hub-based and entirely built with common Store/Phone controls. So all the code is shared: binary through the PCL, or as source in the Shared project. Needless to say I like this approach a lot… Here’s the full project, it was built with Visual Studio 2013 Update 2 (RC): U2UC.WinUni.CustomControlSample.zip (303.6KB) Enjoy! XAML Brewer