Navigating in Xamarin

I was listening to a podcast (Merge Conflict) recently about the latest changes in Xamarin, and being a curious soul, decided it was time to at least understand what was going on. This time, the big new feature was the Xamarin Live Player which promises much faster debugging through your actual phone! Instead of being stuck using the creaky old Android emulator on Windows, or waiting 2 – 5 minutes on every build with your phone plugged in, you could now, with the power of the internet, debug wirelessly almost instantly. Obviously, I was suspicious, but this sounded like fun, so I jumped in.

Getting setup was a bit of a chore, I will admit. Most of the trouble was linked to being an early adopter. You see, Xamarin Live Player wasn’t truly released yet, just part of the latest preview of Visual Studio (v15.3 to be exact). So I had to get that, install almost all features (say goodbye to about 40GB on your hard drive, sorry ultrabook owners), and then I was basically ready to go. The final step was installing their app on my phone, and I was ready to go.

Within about 10 minutes I had the demo project running on my phone, pretty good I thought. I used the Master/Detail project template and that came with some basic navigation to boot. Everything looked great…but was it?

Being a big fan of MVVM, I really have 3 things I need in place before I can start building an application.

  1. A base class implementing INotifyPropertyChanged. Luckily this project came with one called ObservableObject.
  2. A class implementing ICommand. Again, Xamarin has us covered here, with their implementation imaginatively named Command.
  3. Some kind of ViewModel first navigation system, which appears to be missing.

So, before I get into what’s missing, I want to say that obviously, it’s not Xamarin’s job to create this stuff for us. I don’t need to be spoon-fed. Also, I get that they’re trying to set us up with a working system to get us rolling, but I don’t think this is it.

I’ve never liked View-first navigation in MVVM apps. I don’t really get how you’re supposed to be able to pass anything around, unless you’re constantly creating a View, then passing the newly created ViewModel into that in the constructor. Gross. Unfortunately, that’s what this demo app does, and it took me a few hours to figure out what everything was and what was doing what, before I realized I needed a better way. In the template you get, they’re basically doing navigation from events in the code-behind of the views (or pages in this case). Again, not a fan.

My first instinct was to do my old favorite, using DataTemplates, and just defining the View / ViewModel pairs explicitly in Xaml somewhere and being done with it. Unfortunately, it looked like this wasn’t going to fly in Xamarin.

So I did what I always do, started googling it. And it worked. I came across a library called VMFirstNav. It contained most of what I wanted, but had a little more in it than I wanted. Using their implementation, you have to make all Views implement an interface telling the library what ViewModel to link it to, and then all ViewModels have to implement another interface. It wasn’t a dealbreaker, but I wanted to see what he was actually doing. The nice thing of all that was that it would automagically figure out what View to load when you change (or push) to a new ViewModel.

This is where I want to thank CodeMillMatt. Without his code, I would have taken a lot longer to figure out how this all works. It’s good stuff dude.

OK, so what I did was take his library and just boil it down to the one important class, the NavigationService, which I named Navigator. I didn’t bother making a new github project, or putting it in Nuget, as I don’t think this is really finished. I could see a need for more features depending on what you need, but this is at least a solid starting point.

Here’s the code for the class –

And here’s how to use it, once you’ve got it in place. It has a static constructor, so it’s essentially a singleton, so you don’t need to go passing it in and out of every class. It’s a little more decoupled, but I prefer it that way.


There’s 2 ways of using it.

  1. Explicitly specify all the View / View Model pairs on startup. In the past I’ve liked this method as at least you know where they are and how it works. The other advantage of this is you can name these classes whatever you want.
     private void SetupAllViewToViewModelPairs()
     {
         var nav = Navigator.Instance;
    
         nav.Register(typeof(LoggingViewModel), typeof(LoggingView));
         nav.Register(typeof(AnotherViewModel), typeof(AnotherView));
     }
    
  2. Follow a simple naming convention, and the service will automagically figure out what View to load when you tell it to load a certain View Model. The convention can be changed (it’s your code now after all). As long as you follow the scheme below, you’ll be good.
     [ClassName]View.xaml
     [ClassName]ViewModel.cs
    

OK, then to use it, you’re basically just doing the following –

var vm = new [ClassName]ViewModel();
await Navigator.Instance.PushAsync(vm);

Easy.

Bear in mind, there is no error checking on this code, so maybe tidy that up a little if you plan on using it. The only part you would need to be more careful of is probably the automatic View locating part.

Just to wrap this up. I played with Xamarin for a couple of days, but found the limitations to be too hard to work with. I’m sure there’s a lot of uses for it, but we don’t do a lot with web services at my work, so I haven’t got any excuses to work with it.

If you’ve got any comments on the code, or you’ve built anything cool in Xamarin that you’d like to show off, let me know in the comments.

Automating App Assets With Inkscape

I’ve been building a windows desktop application for the last year or so and I think it’s almost ready for release. The final step for any app, be it Windows, Android or Apple involves a lot of build optimizations and asset creation. Being lazy, I had already set up my build process to one-click, but my asset creation (icons, logos, splash screens) was still a very manual process. To make things even worse, I just had to change my application name, as it was already taken in the Windows Store, so I would now have to go through changing all my assets.

This is how I came up with the idea of automating my assets from a SVG file, using Inkscape. Now, none if this is probably ground-breaking, but I thought that I might as well share what I’ve got to hopefully make someone else’s life easier. This method will work for Android and Apple assets too, but you’re going to need to create a different batch file specific to those icons required, but the it’s essentially the same.

Step 1 is creating a new SVG file in Inkscape. Microsoft requires a whole bunch of different images, but they basically break down into 2 sets, a square icon and a rectangular one (with the weirdest proportion of 31:15). Since resolution doesn’t really matter in SVG files, I’d recommend you create a square icon of 150 x 150, and the rectangular at 310 x 150. That way, your images will be correct proportionally. Put whatever you want into those icons, just make sure they stay within those confines.

In my example below, I’ve shaded the background a light gray, just to make it easier to see the boundaries, but in your icon, make the background whatever you need it to be.

Blog1

OK, now you need to group each icon and apply an ID to each of them. Highlight all the items in the square icon first, and use CTRL-G to group them as one item. Now do the same with the wide icon. Finally, right-click one of the icons and select Object Properties…. With this open, name each of your icons. In my example, I’ve simply named them Logo and LogoWide.

Blog2

OK, so that’s mostly it, now we just use the Inkscape command-line utility to export each of those icons to multiple resolutions under multiple filenames. The utility is pretty powerful, you can do a lot of different kinds of export in it, I’ve only outlined the basic one in my script below, but here’s the reference for it

Here’s the script. Basically you’ll only have to change the variables at the top of the batch script. Take this file, change to point to your installation of Inkscape, your SVG file and your logo IDs (from Inkscape) and save it as a .bat file. Then give it a shot.

SET INKSCAPE=C:\Program Files\Inkscape\Inkscape.com
SET SVG_FILE=C:\GitHub\notedui\jott.svg
SET ASSETS_PATH=C:\Github\notedui\DesktopBridge\Images
SET ID_LOGO=Logo
SET ID_LOGO_WIDE=LogoWide

REM Square 71x71 Logo
"%INKSCAPE%" --file "%SVG_FILE%" --export-png "%ASSETS_PATH%\Square71.scale-400.png" --export-id "%ID_LOGO%" --export-id-only --export-width 284
"%INKSCAPE%" --file "%SVG_FILE%" --export-png "%ASSETS_PATH%\Square71.scale-200.png" --export-id "%ID_LOGO%" --export-id-only --export-width 142
"%INKSCAPE%" --file "%SVG_FILE%" --export-png "%ASSETS_PATH%\Square71.scale-150.png" --export-id "%ID_LOGO%" --export-id-only --export-width 107
"%INKSCAPE%" --file "%SVG_FILE%" --export-png "%ASSETS_PATH%\Square71.scale-125.png" --export-id "%ID_LOGO%" --export-id-only --export-width 89
"%INKSCAPE%" --file "%SVG_FILE%" --export-png "%ASSETS_PATH%\Square71.scale-100.png" --export-id "%ID_LOGO%" --export-id-only --export-width 71

REM Square 150x150 Logo
"%INKSCAPE%" --file "%SVG_FILE%" --export-png "%ASSETS_PATH%\Square150.scale-400.png" --export-id "%ID_LOGO%" --export-id-only --export-width 600
"%INKSCAPE%" --file "%SVG_FILE%" --export-png "%ASSETS_PATH%\Square150.scale-200.png" --export-id "%ID_LOGO%" --export-id-only --export-width 300
"%INKSCAPE%" --file "%SVG_FILE%" --export-png "%ASSETS_PATH%\Square150.scale-150.png" --export-id "%ID_LOGO%" --export-id-only --export-width 225
"%INKSCAPE%" --file "%SVG_FILE%" --export-png "%ASSETS_PATH%\Square150.scale-125.png" --export-id "%ID_LOGO%" --export-id-only --export-width 188
"%INKSCAPE%" --file "%SVG_FILE%" --export-png "%ASSETS_PATH%\Square150.scale-100.png" --export-id "%ID_LOGO%" --export-id-only --export-width 150

REM Square 310x310 Logo
"%INKSCAPE%" --file "%SVG_FILE%" --export-png "%ASSETS_PATH%\Square310.scale-400.png" --export-id "%ID_LOGO%" --export-id-only --export-width 1240
"%INKSCAPE%" --file "%SVG_FILE%" --export-png "%ASSETS_PATH%\Square310.scale-200.png" --export-id "%ID_LOGO%" --export-id-only --export-width 620
"%INKSCAPE%" --file "%SVG_FILE%" --export-png "%ASSETS_PATH%\Square310.scale-150.png" --export-id "%ID_LOGO%" --export-id-only --export-width 465
"%INKSCAPE%" --file "%SVG_FILE%" --export-png "%ASSETS_PATH%\Square310.scale-125.png" --export-id "%ID_LOGO%" --export-id-only --export-width 388
"%INKSCAPE%" --file "%SVG_FILE%" --export-png "%ASSETS_PATH%\Square310.scale-100.png" --export-id "%ID_LOGO%" --export-id-only --export-width 310

REM Square 44x44 Logo
"%INKSCAPE%" --file "%SVG_FILE%" --export-png "%ASSETS_PATH%\Square44.scale-400.png" --export-id "%ID_LOGO%" --export-id-only --export-width 176
"%INKSCAPE%" --file "%SVG_FILE%" --export-png "%ASSETS_PATH%\Square44.scale-200.png" --export-id "%ID_LOGO%" --export-id-only --export-width 88
"%INKSCAPE%" --file "%SVG_FILE%" --export-png "%ASSETS_PATH%\Square44.scale-150.png" --export-id "%ID_LOGO%" --export-id-only --export-width 66
"%INKSCAPE%" --file "%SVG_FILE%" --export-png "%ASSETS_PATH%\Square44.scale-125.png" --export-id "%ID_LOGO%" --export-id-only --export-width 55
"%INKSCAPE%" --file "%SVG_FILE%" --export-png "%ASSETS_PATH%\Square44.scale-100.png" --export-id "%ID_LOGO%" --export-id-only --export-width 44

"%INKSCAPE%" --file "%SVG_FILE%" --export-png "%ASSETS_PATH%\Square44.targetsize-256.png" --export-id "%ID_LOGO%" --export-id-only --export-width 256
"%INKSCAPE%" --file "%SVG_FILE%" --export-png "%ASSETS_PATH%\Square44.targetsize-48.png" --export-id "%ID_LOGO%" --export-id-only --export-width 48
"%INKSCAPE%" --file "%SVG_FILE%" --export-png "%ASSETS_PATH%\Square44.targetsize-24.png" --export-id "%ID_LOGO%" --export-id-only --export-width 24
"%INKSCAPE%" --file "%SVG_FILE%" --export-png "%ASSETS_PATH%\Square44.targetsize-16.png" --export-id "%ID_LOGO%" --export-id-only --export-width 16

REM Store Logo
"%INKSCAPE%" --file "%SVG_FILE%" --export-png "%ASSETS_PATH%\StoreLogo.scale-400.png" --export-id "%ID_LOGO%" --export-id-only --export-width 200
"%INKSCAPE%" --file "%SVG_FILE%" --export-png "%ASSETS_PATH%\StoreLogo.scale-200.png" --export-id "%ID_LOGO%" --export-id-only --export-width 100
"%INKSCAPE%" --file "%SVG_FILE%" --export-png "%ASSETS_PATH%\StoreLogo.scale-150.png" --export-id "%ID_LOGO%" --export-id-only --export-width 75
"%INKSCAPE%" --file "%SVG_FILE%" --export-png "%ASSETS_PATH%\StoreLogo.scale-125.png" --export-id "%ID_LOGO%" --export-id-only --export-width 63
"%INKSCAPE%" --file "%SVG_FILE%" --export-png "%ASSETS_PATH%\StoreLogo.scale-100.png" --export-id "%ID_LOGO%" --export-id-only --export-width 50

REM Badge Logo
"%INKSCAPE%" --file "%SVG_FILE%" --export-png "%ASSETS_PATH%\BadgeLogo.scale-400.png" --export-id "%ID_LOGO%" --export-id-only --export-width 96
"%INKSCAPE%" --file "%SVG_FILE%" --export-png "%ASSETS_PATH%\BadgeLogo.scale-200.png" --export-id "%ID_LOGO%" --export-id-only --export-width 48
"%INKSCAPE%" --file "%SVG_FILE%" --export-png "%ASSETS_PATH%\BadgeLogo.scale-150.png" --export-id "%ID_LOGO%" --export-id-only --export-width 36
"%INKSCAPE%" --file "%SVG_FILE%" --export-png "%ASSETS_PATH%\BadgeLogo.scale-125.png" --export-id "%ID_LOGO%" --export-id-only --export-width 30
"%INKSCAPE%" --file "%SVG_FILE%" --export-png "%ASSETS_PATH%\BadgeLogo.scale-100.png" --export-id "%ID_LOGO%" --export-id-only --export-width 24


REM Wide 310x150 Logo
"%INKSCAPE%" --file "%SVG_FILE%" --export-png "%ASSETS_PATH%\Wide310.scale-400.png" --export-id "%ID_LOGO_WIDE%" --export-id-only --export-width 1240
"%INKSCAPE%" --file "%SVG_FILE%" --export-png "%ASSETS_PATH%\Wide310.scale-200.png" --export-id "%ID_LOGO_WIDE%" --export-id-only --export-width 620
"%INKSCAPE%" --file "%SVG_FILE%" --export-png "%ASSETS_PATH%\Wide310.scale-150.png" --export-id "%ID_LOGO_WIDE%" --export-id-only --export-width 465
"%INKSCAPE%" --file "%SVG_FILE%" --export-png "%ASSETS_PATH%\Wide310.scale-125.png" --export-id "%ID_LOGO_WIDE%" --export-id-only --export-width 388
"%INKSCAPE%" --file "%SVG_FILE%" --export-png "%ASSETS_PATH%\Wide310.scale-100.png" --export-id "%ID_LOGO_WIDE%" --export-id-only --export-width 310

REM Splash Screen
"%INKSCAPE%" --file "%SVG_FILE%" --export-png "%ASSETS_PATH%\SplashScreen.scale-400.png" --export-id "%ID_LOGO_WIDE%" --export-id-only --export-width 2480
"%INKSCAPE%" --file "%SVG_FILE%" --export-png "%ASSETS_PATH%\SplashScreen.scale-200.png" --export-id "%ID_LOGO_WIDE%" --export-id-only --export-width 1240
"%INKSCAPE%" --file "%SVG_FILE%" --export-png "%ASSETS_PATH%\SplashScreen.scale-150.png" --export-id "%ID_LOGO_WIDE%" --export-id-only --export-width 930
"%INKSCAPE%" --file "%SVG_FILE%" --export-png "%ASSETS_PATH%\SplashScreen.scale-125.png" --export-id "%ID_LOGO_WIDE%" --export-id-only --export-width 775
"%INKSCAPE%" --file "%SVG_FILE%" --export-png "%ASSETS_PATH%\SplashScreen.scale-100.png" --export-id "%ID_LOGO_WIDE%" --export-id-only --export-width 620

It takes about 30 second to build all those PNGs, but assuming you’re not rebuilding them every time you build the app, this is quite the time-saver. Let me know in the comments if you’ve come up with anything better.

Prototyping a puzzle game in C#

I had an idea recently for a puzzle game. Now I’ve had ideas for games in the past, but after second inspection they were either way too complicated for me to take on by myself or the idea didn’t hold up. This one, however, seemed to be a winner, so I decided to spend some time throwing together a prototype.

Over the last year I’ve taken a couple of online courses about Unity with the hope that I can pick up enough skills to be able to create my own game someday. I think this could be the perfect game to finally give it a shot. The problem for me is that I have trouble remembering the details of Unity while focusing on trying to make a real prototype of this game. Something’s going to slip, either I spend every 2 minutes googling on how to do basic things, or I spent my time focusing on the actualy game logic. In this case, the game logic was going to be complex, so I wanted 100% focus on that for now.

In my day job I work with WPF and C# all day long so I’m very comfortable with it (“very comfortable” is about as much praise as I’ll ever give myself in any skill, I was asked in an interview once to rate my skills in C# and I ended up saying 6/10, for a job I wanted). So the obvious thing for me was to throw together a prototype using what I work best with, and that’s what I’m going to talk about here.

First thing you’ll need is an MVVM library. Not to toot my own horn, but I created JustMVVM for this purpose, so feel free to use it if you want, it’s available on Nuget too.

This puzzle game idea I have could be generically described as similar to Tetris, so I have a basic grid and some blocks. Here’s the View layout, I’ve stripped out some of the less useful stuff.

<Window xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
        xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
        xmlns:local="clr-namespace:PuzzlePrototype"
        Title="MainWindow"
        SizeToContent="WidthAndHeight"
        WindowStartupLocation="CenterScreen"
        mc:Ignorable="d">

    <Window.DataContext>
        <local:MainWindowViewModel />
    </Window.DataContext>

    <Grid>
        <ItemsControl x:Name="GameGrid"
                      ItemsSource="{Binding Blocks}">

            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <Canvas Width="{Binding Width}"
                            Height="{Binding Height}"
                            Background="#FF444444">
                    </Canvas>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>

            <ItemsControl.ItemContainerStyle>
                <Style>
                    <Setter Property="Canvas.Bottom"
                            Value="{Binding Bottom}" />
                    <Setter Property="Canvas.Left"
                            Value="{Binding Left}" />
                </Style>
            </ItemsControl.ItemContainerStyle>

            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Rectangle Canvas.Left="{Binding Left}"
                               Canvas.Bottom="{Binding Bottom}"
                               Width="{Binding BlockSize}"
                               Height="{Binding BlockSize}"
                               Stroke="White">
                        <Rectangle.Fill>
                            <SolidColorBrush Color="{Binding Color}" />
                        </Rectangle.Fill>
                    </Rectangle>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </Grid>
</Window>

The ItemsControl just contains a collection of blocks, allowing you to bind them to the ViewModel using MVVM.

There’s also a little magic that can be added to the Canvas inside the ItemsControl.ItemsPanel called FluidMoveBehavior. If you add this to the View, you’ll automatically get animated transitions when the blocks move positions. It’s pretty much up to you if you want to make a simple blocky game, or want a little more smooth animation in it. Here’s the FluidMoveBehavior

<Canvas Width="{Binding Width}"
        Height="{Binding Height}"
        Background="#FF444444">
    <i:Interaction.Behaviors>
        <ei:FluidMoveBehavior AppliesTo="Children"
                                Duration="0:0:0.5">
            <ei:FluidMoveBehavior.EaseY>
                <SineEase EasingMode="EaseIn" />
            </ei:FluidMoveBehavior.EaseY>
            <ei:FluidMoveBehavior.EaseX>
                <SineEase EasingMode="EaseIn" />
            </ei:FluidMoveBehavior.EaseX>
        </ei:FluidMoveBehavior>
    </i:Interaction.Behaviors>
</Canvas>

The SineEase can be substituted for other easing functions.

Here’s the bare bones for the ViewModel to get things going –

public class MainWindowViewModel : MVVMBase
{
    public const int NUM_COLS = 10;
    public const int NUM_ROWS = 16;
    public const int BLOCK = 40;

    private ObservableCollection<Block> _blocks;
    public ObservableCollection<Block> Blocks
    {
        get { return _blocks; }
        set
        {
            _blocks = value;
            OnPropertyChanged();
        }
    }

    public double Width { get { return NUM_COLS * BLOCK; } }
    public double Height { get { return NUM_ROWS * BLOCK; } }

    public MainWindowViewModel()
    {
        Blocks = new ObservableCollection<Block>();
    }
}

For this prototype, it’s easiest to have all your grid size code in one place, so I’ve stored them in constants at the top. The Width and Height are bound to the view so it’ll scale appropriately. In this case, we’re creating a window 400 x 640, where each block is 40 x 40.

This is also where I ended up throwing all of my code while I was testing this out, but feel free to make it as complicated or simple as you place.

Finally, the last class required is Block.cs.

public class Block : MVVMBase
{
    public static List<Color> ColorList = new List<Color>()
    {
        (Color)ColorConverter.ConvertFromString("#860DFF"),
        (Color)ColorConverter.ConvertFromString("#3D0CE8"),
        (Color)ColorConverter.ConvertFromString("#000CFF"),
        (Color)ColorConverter.ConvertFromString("#0C50E8"),
        (Color)ColorConverter.ConvertFromString("#0D97FF")
    };

    public int BlockSize { get; set; } = MainWindowViewModel.BLOCK;

    private double _bottom;
    public double Bottom
    {
        get { return _bottom; }
        set
        {
            _bottom = value;
            OnPropertyChanged();
        }
    }

    private double _left;
    public double Left
    {
        get { return _left; }
        set
        {
            _left = value;
            OnPropertyChanged();
        }
    }

    private int _x;
    public int X
    {
        get { return _x; }
        set
        {
            _x = value;
            Left = _x * MainWindowViewModel.BLOCK;
        }
    }

    private int _y;
    public int Y
    {
        get { return _y; }
        set
        {
            _y = value;
            Bottom = _y * MainWindowViewModel.BLOCK;
        }
    }

    public Color Color { get; set; }

    private static Random _random = new Random(DateTime.Now.Millisecond);

    public Block(int x, int y)
        : this(x, y, ColorList[_random.Next(ColorList.Count)])
    { }

    public Block(int x, int y, Color color)
    {
        X = x;
        Y = y;

        Color = color;
    }

    public override string ToString()
    {
        return $"({ X }, {Y}), { Color.ToString() }";
    }
}

There’s not a lot to it really, most of this code just exists to scale your block units (0, 0) to (9, 15) to WPF pixel coordinates.

The reason I created this was to stop myself wasting any of my (little) free time navigating Unity. Hopefully some day in the future I’ll be so proficient in Unity that I won’t need this middle step, but for now it worked perfectly. If and when I’m happy with my game, I’ll make sure it all works and then focus on recreating the hard work in Unity to create the cross-platform game I’m looking for.

Hopefully some of you folks out there can also benefit from creating something in a familiar environment with the language you’re most confortable with.

All this source code is available on Github here.

Let me know what you think in the comments.

Vertical Airspace

Sometimes when you’re working in WPF, you’ll come across an issue that just stops you dead in your tracks. The kind of issue that makes you wonder how in the hell this problem can still exist in version 4+ of a product. Well, today I’m going to talk about one of those, namely Airspace.

Odds are that you haven’t heard of airspace, it’s one of those weird issues that you don’t need to know about until you need to know about it. Here’s the best simple explanation I could find about it. Basically, the problem rears its head when you’re trying to host a WinForms control inside a WPF hosting window or vice-versa. What happens is that the WinForms control has to be on the topmost layer, no matter what. Even if you try to change the z-index of another control, the WinForms control will always be on top. In reality, this means you can’t show any modal dialogs on top of any WinForms controls.

OK, OK, I know, you’re probably thinking this won’t affect me, it doesn’t really matter, I never use any WinForms controls inside my super-shiny-awesome WPF apps. Welp, maybe you’re right, but maybe, just maybe you’re going to use the WebBrowser control!

horrified

The WebBrowser control is a WinForms control (they don’t like to publicize that fact) that’s basically been wrapped for WPF.

I found this out myself just a few weeks ago, when I tried to throw some Markdown preview into my application. I thought the easiest thing to do would be to just throw in a standard-issue WebBrowser and render to it. Little did I know the rabbit hole I was about to fall into. All worked great until I tried to put my dialog on top of the browser and it just didn’t. I can’t show the original example here, but I threw together a quick example of what happened.

airspacebad

The highlighted box above has a bunch of standard WPF controls, while the WebBrowser takes up most of the space. When I hit the settings button it’s supposed to show a dialog on top of the entire window and darken the background a little bit. As you can see, the dialog can’t be seen as it’s covered by the WebBrowser but you can see the top part has the darkened background.

I did a little searching on how to fix the problem, thinking it would be an easy fix, which led me here and to a false solution here which stated it would be fixed in WPF 4.5, but it never came to be. I guess the official solution is waaaaay more complicated than it looks. Some people recommended just hiding the WinForms control when showing a dialog, which, in theory would work, but is not very subtle, especially if it’s not a full-screen dialog.

I went further into the internet and came across both CEFSharp and Awesomium which both seem super powerful and useful, but also over-powered for what I needed. Add to the fact that both have a lot of JS native code calls to do the more complicated parts, and I was starting to get a little scared off.

Finally, after some thinking, I decided I should try and fix the problem that I’m actually having, that I can’t show a dialog on top, so I came up with a pretty hacky little workaround that I wanted to share with everyone.

AirspacePanel aims to fix this problem by allowing you to host any content you like inside of it, and swapping out the content for a screenshot of the content when you need to place a modal dialog on top of it. This swap is done by using the dependency property FixAirspace. Here’s an example –

xmlns:asf="clr-namespace:AirspaceFixer;assembly=AirspaceFixer"

<asf:AirspacePanel FixAirspace="{Binding FixAirspace}">
    <WebBrowser x:Name="Browser" />
</asf:AirspacePanel>

The entire project (in all it’s tiny glory) is available here on github which contains a sample project if you just want to see it. Here’s the screenshot from above all fixed with AirspacePanel.

airspacegood

You can also find it in Nuget through Visual Studio.

If anyone does give it a shot, let me know what you think. For me, it fixes a small annoyance, but I’d like to hear some other opinions.

Automate Your App Settings View in WPF

 

If you’re anything like me, you’re always coming up with new ideas for applications. Since WPF is my favorite UI framework, I usually end up creating it in C# and WPF. Things go great for a while, the application gets to a working state and I’m ready to preview it to the world (or a friend), but there’s still one thing I need to do – the settings screen.

The requirements for a setting screen can vary depending on the complexity of your application, but even the simplest ones usually have a handful of settings. Every time I get to this stage of the process I end up slacking off and not really finishing it properly.

So, here’s my one-stop solution to never having to create another settings screen ever again. Just implement the steps below and you’ll have a simple settings screen that binds to a class with special attributes to handle some of the finer details. Let’s jump in –

Settings Classes

First we need a simple class to contain our settings. In this example we’ll just stick with 5 settings

public class AppSettings
{
    public string LogFile { get; set; }
    public bool LogAllData { get; set; }
    public bool LightTheme { get; set; }
    public int NumberOfUsers { get; set; }
    public enum eStartupView { get; set; }
}

Now, obviously, you’re probably storing these settings somewhere, either in SQL or some kind of file, but I’ll leave those details up to you.

We want to be able to add some data to these settings so we can display a description of the setting to the user on the Settings screen. There may be some other data you’ll need to add to them to organize the settings or even hide some from the user. To do this, we’re going to create an Attribute class –

public class SettingAttribute : Attribute
{
    public string Description { get; set; }
    public bool Visible { get; set; }
}

Now we can use this attribute class to add the extra information into our settings, so our AppSettings class becomes this

public class AppSettings
{
    [Settings(Description = "Log file location")]
    public string LogFile { get; set; }

    [Settings(Description = "Do you want to log all data?")]
    public bool LogAllData { get; set; }

    [Settings(Description = "Use the light theme?")]
    public bool LightTheme { get; set; }

    [Settings(Description = "How many users are in the system?)]
    public int NumberOfUsers { get; set; }

    [Settings(Description = "What view should we show on startup?")]
    public enum eStartupView { get; set; }
}

ViewModels

Now we can create the ViewModel for the Settings View. The goal in the SettingsViewModel is to read all the properties from AppSettings using reflection and create a list of SettingsItemViewModels. Let’s start with the SettingsItemViewModel. I have it inheriting from MVVMBase which is a base class that inherits INotifyPropertyChanged. If you’re looking for an MVVM framework may I suggest JustMVVM, I wrote it, but it’s the simplest MVVM framework around, and that’s why I did it.

public class SettingsItemViewModel : MVVMBase
{
    public string Name { get; set; }
    public string Description { get; set; }
    public Type SettingType { get; set; }
    public bool IsDirty { get; set; }

    private dynamic _value;
    public dynamic Value
    {
        get { return _value; }
        set
        {
            _value = value;
            OnPropertyChanged();

            IsDirty = true;
        }
    }
}

So, this class above is a generic class that can contain any type of setting. This way we can create a list of them, one for each of the properties in AppSettings. The real key to this is using the dynamic type for the property Value. It allows us to set it generically and then check if afterwards to find out the type. IsDirty can also be useful to tell if the setting was actually changed. We’ll see that below.

Here’s the code for the SettingsViewModel which is the view model for the SettingsView UI.

public class SettingsViewModel : MVVMBase
{
    private ObservableCollection<SettingsItemViewModel> _settings;
    public ObservableCollection<SettingsItemViewModel> Settings
    {
        get { return _settings; }
        set
        {
            _settings = value;
            OnPropertyChanged();
        }
    }

    public SettingsViewModel()
    {
        AppSettings appSettings = GetAppSettings();

        Settings = GetAvailableSettings(appSettings);
    }

    public ObservableCollection<SettingsItemViewModel> GetAvailableSettings(Dictionary<string, object> settings)
    {
        var settingsView = new ObservableCollection<SettingsItemViewModel>();

        foreach (var prop in typeof(AppSettings).GetProperties())
        {
            var settingItem = new SettingsItemViewModel();

            foreach (var customAttData in prop.GetCustomAttributesData())
            {
                foreach (var item in customAttData.NamedArguments)
                {
                    var name = item.MemberInfo.Name;

                    if (name == "Description")
                        settingItem.Description = item.TypedValue.Value.ToString();
                }
            }

            settingItem.Name = prop.Name;
            settingItem.Value = settings[prop.Name];

            // Get type once value is set, value will get type dynamically
            settingItem.SettingType = settingsItem.Value.GetType();

            settingItem.IsDirty = false;

            settingsView.Add(settingItem);
        }

        return settingsView;
    }
}

OK, we’ve now got our ObservableCollection<SettingsItemViewModel> ready to go for the View. Let’s take a look at what needs to happen there.

View

OK, the View is pretty straight forward. We’re going to use an ItemsControl to contain our list of settings and we’ll use DataTemplates to figure out what view to display for each setting. Hopefully this will become more clear after you look at the code –

<Grid>
    <ItemsControl ItemsSource="{Binding Settings}">        
        <ItemsControl.ItemTemplate>
            <DataTemplate DataType="{x:Type vm:SettingsItemViewModel}">
                <ContentControl Content="{Binding }">
                    <ContentControl.Style>
                        <Style TargetType="{x:Type ContentControl}">
                            <Style.Triggers>

                                <DataTrigger Binding="{Binding SettingType}"
                                             Value="{x:Type sys:Boolean}">
                                    <Setter Property="ContentTemplate" Value="{StaticResource BooleanSettingTemplate}" />
                                </DataTrigger>

                                <DataTrigger Binding="{Binding SettingType}"
                                             Value="{x:Type sys:Int32}">
                                    <Setter Property="ContentTemplate" Value="{StaticResource IntegerSettingTemplate}" />
                                </DataTrigger>

                                <DataTrigger Binding="{Binding SettingType}"
                                             Value="{x:Type sys:Double}">
                                    <Setter Property="ContentTemplate" Value="{StaticResource DoubleSettingTemplate}" />
                                </DataTrigger>

                                <DataTrigger Binding="{Binding SettingType}"
                                             Value="{x:Type sys:String}">
                                    <Setter Property="ContentTemplate" Value="{StaticResource StringSettingTemplate}" />
                                </DataTrigger>

                                <DataTrigger Binding="{Binding SettingType,
                                                               Converter={StaticResource IsEnumeratorConverter}}"
                                             Value="True">
                                    <Setter Property="ContentTemplate" Value="{StaticResource EnumSettingTemplate}" />
                                </DataTrigger>

                            </Style.Triggers>
                        </Style>
                    </ContentControl.Style>
                </ContentControl>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
</Grid>

The ContentControl inside the ItemsControl has a bunch of triggers that displays a different DataTemplate based on the SettingType of the SettingsItem. This allows us to have different views for each type. Obviously the view for a Boolean settings will be some kind of a checkbox, while the view for an enum would probably be a combobox.

Here are the data templates used to make this magic happen. If you don’t know too much about data templates, this is a good resources. These need to be placed in the resources section somewhere in the View. In this case I put it in the ItemsControl.Resources section.

<ItemsControl.Resources>

    <DataTemplate x:Key="BooleanSettingTemplate">
        <UniformGrid Columns="2"
                     Rows="1">
            <Label HorizontalAlignment="Right"
                   Content="{Binding Description}" />
            <CheckBox HorizontalAlignment="Left"
                      Content=""
                      IsChecked="{Binding Value}" />
        </UniformGrid>
    </DataTemplate>

    <DataTemplate x:Key="IntegerSettingTemplate">
        <UniformGrid Columns="2"
                     Rows="1">
            <Label HorizontalAlignment="Right"
                   Content="{Binding Description}" />
            <wpf:SFNumberTextBox HorizontalAlignment="Left"
                                 Interval="1"
                                 StringFormat="N0"
                                 ValueInt="{Binding Value}" />
        </UniformGrid>
    </DataTemplate>

    <DataTemplate x:Key="DoubleSettingTemplate">
        <UniformGrid Columns="2"
                     Rows="1">
            <Label HorizontalAlignment="Right"
                   Content="{Binding Description}" />
            <wpf:SFNumberTextBox HorizontalAlignment="Left"
                                 Interval="0.5"
                                 StringFormat="N1"
                                 Value="{Binding Value}" />
        </UniformGrid>
    </DataTemplate>

    <DataTemplate x:Key="StringSettingTemplate">
        <UniformGrid Columns="2"
                     Rows="1">
            <Label HorizontalAlignment="Right"
                   Content="{Binding Description}" />
            <TextBox HorizontalAlignment="Left"
                     wpfab:TextFieldExt.ClearTextButton="True"
                     Text="{Binding Value}" />
        </UniformGrid>
    </DataTemplate>

    <DataTemplate x:Key="EnumSettingTemplate">
        <UniformGrid Columns="2"
                     Rows="1">
            <Label HorizontalAlignment="Right"
                   Content="{Binding Description}" />
            <ComboBox ItemsSource="{Binding SettingType,
                                            Converter={StaticResource EnumToArrayConverter}}"
                      SelectedItem="{Binding Value}" />
        </UniformGrid>
    </DataTemplate>

</ItemsControl.Resources>

Alright. Everything’s linked up now. Obviously you can add to this if you have more complicated settings. Some settings may even be complete other classes. Either way, this setup should work pretty smoothly for you.

Converters

Here’s a couple of extra pieces that make it easier to use enums with comboboxes for settings (I’m assuming you have some). They’re just a couple of simple converters that let you bind to an enum without having to explicitly mention the enum type.

public class IsEnumeratorConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (!(value is Type))
            return false;

        var type = value as Type;

        return type.IsEnum;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}


public class EnumToArrayConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (!(value is Type))
            return new List<string>();

        return Enum.GetValues(value as Type);
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

That’s it. Let me know what you think in the comments. I’m always looking for feedback. I’ve been thinking of some variation of this setup for a while now, and I’m looking forward to never manually creating another settings screen ever again.

Dapper vs Rolling-Your-Own

A follow up to DataTable To List

After my last post, I got a lot of good advice on Reddit, mostly on better ways of handling my SQL data. The main point people were bringing up was using ORMs. Now, I’ve heard of the major ORMs, mostly the Entity framework I guess, but I’ve never met or spoken to anyone who’s particularly excited about. I’ve heard a lot of “Good idea, bad execution”. Now I’m not sure if that’s accurate or fair, but that’s what I’ve heard.

Most of the advice I was receiving was to use something called Dapper. After a little research I realized that Dapper was written (or at least co-written) by the same Marc Gravell that wrote FastMember (the project that sped up my reflection code). Quite a coincidence I’d say, I guess this guy knows what he’s doing in C#.

Anyway, I updated my benchmark code to compare what I was doing to using Dapper. Since Dapper actually handles the execution of the command as well as returning it to a type, I had to change my tests a little bit, so it looks like everything’s slower compared to last time, but in this test I’m timing the SQL query and converting to class.

The query I’m using in Dapper is essentially this

TestTable testData = connection.Query<TestTable>(new CommandDefinition("SELECT TOP 5000 * FROM TestTable));

If you take a look on the Github page for this project you’ll see a few other examples of how this works, but this is the simplest case.

I tested this against reading the command into a SqlDataReader and parsing (something a lot of people were recommending I do instead of converting to a DataTable).

Here’s the results –

Dapper runtimes

Now, I don’t know exactly how accurate this is, my benchmarking is pretty sloppy overall (They have more benchmarking on the project site, so feel free to dig a little deeper), but Dapper was faster, or at least essentially the same speed. Add to that the fact that it’s way easier to use than writing your own custom SqlDataReader parsing method for each stored procedure in your project and Dapper gets the win by a mile.

All I know if that I’m going to be giving a real shot on Monday when I get back to work and probably recommending it to the rest of the guys in my department.

DataTable to List

My new job has gotten me involved in a lot more SQL than I’d ever had to in the past. Now this can be interesting, but there’s a whole ton of boilerplate code that goes along with writing SQL, most of which involves converting DataTables to List.

My general opinion on DataTables is that you should immediately convert them into some equivalent C# object representing the properties you’re returning from SQL. I know this isn’t how everyone feels, especially if you’re then taking this data and converting it into some other model-type data, but for the purposes of this post, we’re going to be doing it, stick with me!

I’ve got three different ways of converting the DataTable to List and I’ve benchmarked their relative speeds for your reading pleasure. Here’s the initial setup so you can replicate it.

Creating the Table

CREATE TABLE [TestTable]
(
    [ID] [int] IDENTITY(1,1) NOT FOR REPLICATION NOT NULL,
    [Bit1] [bit] NOT NULL DEFAULT(1),
    [Bit2] [bit] NOT NULL DEFAULT(1),
    [Bit3] [bit] NOT NULL DEFAULT(1),
    [Bit4] [bit] NOT NULL DEFAULT(1),
    [Bit5] [bit] NOT NULL DEFAULT(1),
    [Bit6] [bit] NULL,
    [Bit7] [bit] NULL,
    [Bit8] [bit] NULL,
    [Bit9] [bit] NULL,
    [Bit10] [bit] NULL,
    [Float1] [float] NOT NULL DEFAULT(0.0),
    [Float2] [float] NOT NULL DEFAULT(0.0),
    [Float3] [float] NOT NULL DEFAULT(0.0),
    [Float4] [float] NOT NULL DEFAULT(0.0),
    [Float5] [float] NOT NULL DEFAULT(0.0),
    [Float6] [float] NULL,
    [Float7] [float] NULL,
    [Float8] [float] NULL,
    [Float9] [float] NULL,
    [Float10] [float] NULL,
    [Int1] [int] NOT NULL DEFAULT(0),
    [Int2] [int] NOT NULL DEFAULT(0),
    [Int3] [int] NOT NULL DEFAULT(0),
    [Int4] [int] NOT NULL DEFAULT(0),
    [Int5] [int] NOT NULL DEFAULT(0),
    [Int6] [int] NULL,
    [Int7] [int] NULL,
    [Int8] [int] NULL,
    [Int9] [int] NULL,
    [Int10] [int] NULL,
    [VarChar1] [varchar](100) NOT NULL DEFAULT('TEST'),
    [VarChar2] [varchar](100) NOT NULL DEFAULT('TEST'),
    [VarChar3] [varchar](100) NOT NULL DEFAULT('TEST'),
    [VarChar4] [varchar](100) NOT NULL DEFAULT('TEST'),
    [VarChar5] [varchar](100) NOT NULL DEFAULT('TEST'),
    [VarChar6] [varchar](100) NULL,
    [VarChar7] [varchar](100) NULL,
    [VarChar8] [varchar](100) NULL,
    [VarChar9] [varchar](100) NULL,
    [VarChar10] [varchar](100) NULL,
    PRIMARY KEY CLUSTERED 
    (
        [ID] ASC
    )
WITH 
    (
        PAD_INDEX = OFF, 
        STATISTICS_NORECOMPUTE = OFF, 
        IGNORE_DUP_KEY = OFF, 
        ALLOW_ROW_LOCKS = ON, 
        ALLOW_PAGE_LOCKS = ON
    ) ON [PRIMARY]
) 
ON [PRIMARY]

I’ve also got the test data here, so feel free to grab it. For this test, I had 5000 rows of data (the test file is 1000 records). For the record, this is all MSSQL, and probably won’t work with SQLite without a little tweaking.

To go along with this, I’ve also got a C# class with properties for each of the Columns in the SQL table, here’s that too

public class TestTable
{
    public int ID { get; set; }
    public bool Bit1 { get; set; }
    public bool Bit2 { get; set; }
    public bool Bit3 { get; set; }
    public bool Bit4 { get; set; }
    public bool Bit5 { get; set; }
    public bool? Bit6 { get; set; }
    public bool? Bit7 { get; set; }
    public bool? Bit8 { get; set; }
    public bool? Bit9 { get; set; }
    public bool? Bit10 { get; set; }
    public double Float1 { get; set; }
    public double Float2 { get; set; }
    public double Float3 { get; set; }
    public double Float4 { get; set; }
    public double Float5 { get; set; }
    public double? Float6 { get; set; }
    public double? Float7 { get; set; }
    public double? Float8 { get; set; }
    public double? Float9 { get; set; }
    public double? Float10 { get; set; }
    public int Int1 { get; set; }
    public int Int2 { get; set; }
    public int Int3 { get; set; }
    public int Int4 { get; set; }
    public int Int5 { get; set; }
    public int? Int6 { get; set; }
    public int? Int7 { get; set; }
    public int? Int8 { get; set; }
    public int? Int9 { get; set; }
    public int? Int10 { get; set; }
    public string VarChar1 { get; set; }
    public string VarChar2 { get; set; }
    public string VarChar3 { get; set; }
    public string VarChar4 { get; set; }
    public string VarChar5 { get; set; }
    public string VarChar6 { get; set; }
    public string VarChar7 { get; set; }
    public string VarChar8 { get; set; }
    public string VarChar9 { get; set; }
    public string VarChar10 { get; set; }
}

1 – ForEach

This was my first crack at it, without putting too much thought into it, this was what I thought would be the most efficient way of doing it. Turns out it’s pretty good.

public static List<TestTable> ToListForEach(DataTable dt)
{
    var data = new List<TestTable>();

    foreach (DataRow row in dt.Rows)
    {
        data.Add(new TestTable()
        {
            ID = Convert.ToInt32(row["ID"]),
            Bit1 = Convert.ToBoolean(row["Bit1"]),
            Bit2 = Convert.ToBoolean(row["Bit2"]),
            Bit3 = Convert.ToBoolean(row["Bit3"]),
            Bit4 = Convert.ToBoolean(row["Bit4"]),
            Bit5 = Convert.ToBoolean(row["Bit5"]),
            Bit6 = Convert.ToBoolean(row["Bit6"]),
            Bit7 = Convert.ToBoolean(row["Bit7"]),
            Bit8 = Convert.ToBoolean(row["Bit8"]),
            Bit9 = Convert.ToBoolean(row["Bit9"]),
            Bit10 = Convert.ToBoolean(row["Bit10"]),
            Float1 = Convert.ToDouble(row["Float1"]),
            Float2 = Convert.ToDouble(row["Float2"]),
            Float3 = Convert.ToDouble(row["Float3"]),
            Float4 = Convert.ToDouble(row["Float4"]),
            Float5 = Convert.ToDouble(row["Float5"]),
            Float6 = Convert.ToDouble(row["Float6"]),
            Float7 = Convert.ToDouble(row["Float7"]),
            Float8 = Convert.ToDouble(row["Float8"]),
            Float9 = Convert.ToDouble(row["Float9"]),
            Float10 = Convert.ToDouble(row["Float10"]),
            Int1 = Convert.ToInt32(row["Int1"]),
            Int2 = Convert.ToInt32(row["Int2"]),
            Int3 = Convert.ToInt32(row["Int3"]),
            Int4 = Convert.ToInt32(row["Int4"]),
            Int5 = Convert.ToInt32(row["Int5"]),
            Int6 = Convert.ToInt32(row["Int6"]),
            Int7 = Convert.ToInt32(row["Int7"]),
            Int8 = Convert.ToInt32(row["Int8"]),
            Int9 = Convert.ToInt32(row["Int9"]),
            Int10 = Convert.ToInt32(row["Int10"]),
            VarChar1 = row["VarChar1"].ToString(),
            VarChar2 = row["VarChar2"].ToString(),
            VarChar3 = row["VarChar3"].ToString(),
            VarChar4 = row["VarChar4"].ToString(),
            VarChar5 = row["VarChar5"].ToString(),
            VarChar6 = row["VarChar6"].ToString(),
            VarChar7 = row["VarChar7"].ToString(),
            VarChar8 = row["VarChar8"].ToString(),
            VarChar9 = row["VarChar9"].ToString(),
            VarChar10 = row["VarChar10"].ToString(),
        });
    }

    return data;
}

OK, so this is pretty good and fast. The downside is when you have actual nullable fields that can actually contain null data. In this test, all the data has been faked out, so we don’t have to deal with that, but when you do, this can slow it down considerably.

When you go from a non-null field like

Int6 = Convert.ToInt32(row["Int6"])

and make it nullable, suddenly you have to start writing your code like this –

Int6 = row.IsNull("Int6") ? new int?() : new int?(Convert.ToInt32(row["Int6"])),

or (as emn13 on reddit pointed out to me, a simpler conversion would be)

Int6 = row["Int6"] as int?

Obviously the more you have of that, the worse it gets. This leads us to

2 – LINQ

One of the guys at my work showed me this way. I’m pretty comfortable with LINQ, but I didn’t know you could get an enumerable for a DataTable, and I knew nothing about the Field structure. Here’s what it looks like

public static List<TestTable> ToListLinq(DataTable dt)
{
    return dt.AsEnumerable().Select(item => new TestTable()
    {
        ID = item.Field<int>(nameof(TestTable.ID)),
        Bit1 = item.Field<bool>(nameof(TestTable.Bit1)),
        Bit2 = item.Field<bool>(nameof(TestTable.Bit2)),
        Bit3 = item.Field<bool>(nameof(TestTable.Bit3)),
        Bit4 = item.Field<bool>(nameof(TestTable.Bit4)),
        Bit5 = item.Field<bool>(nameof(TestTable.Bit5)),
        Bit6 = item.Field<bool?>(nameof(TestTable.Bit6)),
        Bit7 = item.Field<bool?>(nameof(TestTable.Bit7)),
        Bit8 = item.Field<bool?>(nameof(TestTable.Bit8)),
        Bit9 = item.Field<bool?>(nameof(TestTable.Bit9)),
        Bit10 = item.Field<bool?>(nameof(TestTable.Bit10)),
        Float1 = item.Field<double>(nameof(TestTable.Float1)),
        Float2 = item.Field<double>(nameof(TestTable.Float2)),
        Float3 = item.Field<double>(nameof(TestTable.Float3)),
        Float4 = item.Field<double>(nameof(TestTable.Float4)),
        Float5 = item.Field<double>(nameof(TestTable.Float5)),
        Float6 = item.Field<double?>(nameof(TestTable.Float6)),
        Float7 = item.Field<double?>(nameof(TestTable.Float7)),
        Float8 = item.Field<double?>(nameof(TestTable.Float8)),
        Float9 = item.Field<double?>(nameof(TestTable.Float9)),
        Float10 = item.Field<double?>(nameof(TestTable.Float10)),
        Int1 = item.Field<int>(nameof(TestTable.Int1)),
        Int2 = item.Field<int>(nameof(TestTable.Int2)),
        Int3 = item.Field<int>(nameof(TestTable.Int3)),
        Int4 = item.Field<int>(nameof(TestTable.Int4)),
        Int5 = item.Field<int>(nameof(TestTable.Int5)),
        Int6 = item.Field<int?>(nameof(TestTable.Int6)),
        Int7 = item.Field<int?>(nameof(TestTable.Int7)),
        Int8 = item.Field<int?>(nameof(TestTable.Int8)),
        Int9 = item.Field<int?>(nameof(TestTable.Int9)),
        Int10 = item.Field<int?>(nameof(TestTable.Int10)),
        VarChar1 = item.Field<string>(nameof(TestTable.VarChar1)),
        VarChar2 = item.Field<string>(nameof(TestTable.VarChar2)),
        VarChar3 = item.Field<string>(nameof(TestTable.VarChar3)),
        VarChar4 = item.Field<string>(nameof(TestTable.VarChar4)),
        VarChar5 = item.Field<string>(nameof(TestTable.VarChar5)),
        VarChar6 = item.Field<string>(nameof(TestTable.VarChar6)),
        VarChar7 = item.Field<string>(nameof(TestTable.VarChar7)),
        VarChar8 = item.Field<string>(nameof(TestTable.VarChar8)),
        VarChar9 = item.Field<string>(nameof(TestTable.VarChar9)),
        VarChar10 = item.Field<string>(nameof(TestTable.VarChar10)),
    }).ToList();
}

So, I’m going to give you a sneak peak at the end results and let you know that this is the fastest version. If you’re looking to turn a DataTable into a List manually, this is your guy. Super fast, and handles nullable fields with ease.

3 – Reflection

Now, I know everyone gets so hung up on speed with reflection, and that, after all, is the entire reason I’m doing this, but if you’re looking for a nice generic way of converting DataTables, I think you’ll like this.

The trick to speeding this up a lot mostly relies on someone else’s smarts. The snippet below uses a project called FastMember by Marc Gravell. Here he is describing how it came to be. Now, I didn’t spend much time looking into it, I just gave it a try and it worked great, so please feel free to read more on the Github site and his blog if you’re not feeling comfortable. Luckily for us, there’s a Nuget package available for FastMember, so just include that, and use the code below, you’ll be fine.

public static List<TestTable> ToListReflection(DataTable dt)
{
    return (List<TestTable>)dt.DataTableToList<TestTable>();
}

private static readonly IDictionary<Type, IEnumerable<PropertyInfo>> _Properties =
    new Dictionary<Type, IEnumerable<PropertyInfo>>();

public static IEnumerable<T> DataTableToList<T>(this DataTable table) where T : class, new()
{
    var objType = typeof(T);
    IEnumerable<PropertyInfo> properties;

    lock (_Properties)
    {
        if (!_Properties.TryGetValue(objType, out properties))
        {
            properties = objType.GetProperties().Where(property => property.CanWrite);
            _Properties.Add(objType, properties);
        }
    }

    var list = new List<T>(table.Rows.Count);

    Parallel.ForEach<DataRow>(table.AsEnumerable().Skip(1), row => {
        var obj = new T();

        foreach (var prop in properties)
        {
            if (prop != null)
            {
                Type t = Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType;

                object propertyValue = (row[prop.Name] == null) ? null : Convert.ChangeType(row[prop.Name], t);

                var accessors = TypeAccessor.Create(objType);
                accessors[obj, prop.Name] = propertyValue;
            }
        }

        list.Add(obj);
    });

    return list;
}

This runs pretty great on its own, but by using Parallel in the ForEach we’re able to at least half our time. If you’re running a 4 core or even an 8 core machine, it can be even better, but YMMV.

So, obviously this method is a little slower, but what you lose in speed, you make up for in flexibility. You’ll never have to add or remove code when you change your stored procedure. You’ll never have to write boiler plate code like in Methods 1 and 2 ever again. Just keep in mind that this works best for small result sets.

Results

OK, here’s the final results.

DataTable to Linq runtimes

It’s pretty much as we’d expect for methods 1 and 2. If you have more nullable fields, 1 will get slower and slower, almost to the speed of method 3, so if you’re looking to do it manually, go with 2. The one thing that amazes me is how close to LINQ speeds we can get with Reflection and FastMember, so give it a try.

If you’re going with 2, here’s a SQL query that will auto generate all the class code for you. It’s pretty sweet.

OK, that’s it. Generally from now on, I think I’ll be using a combination of 2 and 3, depending on the situation. Let me know in the comments if you found anything questionable.

Command-Line into ClickOnce

 

The company I’m with right now has totally bought into ClickOnce. I’ll admit that before I started working here I’d never heard of it. In theory it seems like a nice idea, and generally it seems to work well, but like a lot of Microsoft products, it’s kind of stagnating. I get the impression Microsoft is calling it done on this one, and if you google it, you’ll get some great results like these.

I’m not here right now to discuss the merits or downsides of ClickOnce, I’m just going to describe my (painful) experiences attempting to get command-line access into my application.

I’m a big fan of shortcuts, especially AutoHotKey, so I thought I’d create a shortcut to some of the most-used functions. I’ve done it before and it worked great, how much different could this be…

First things first, ClickOnce doesn’t tell you where it’s installed, so part one of this, is find the application you’ve deployed. The best way I could find to do this was to go to the Start Menu and locate the shortcut. Normally, this would be just a shortcut, and point you in the right direction, right? Nope, it’s actually an application reference, which it turns out, you can use to reference the real app.

On my Win 8.1 system I found this shortcut here – C:\Users\**YOU**\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\MyAwesomeApp.

The application I was trying to use here was a WinForms app, so YMMV if you’re trying this in WPF or straight up in a console app. Hopefully it’s similar enough that you can hack along here with me.

OK, locate the application entry point, in WinForms this is Program.cs. You’ll need to add a check for the args being passed in and, in my case, attach a console app so the user can see what’s actually happening as you’re working.

static class Program
{
    [DllImport("kernel32.dll")]
    private static extern bool AttachConsole(int dwProcessId);
    private const int ATTACH_PARENT_PROCESS = -1;

    static void Main()
    {
        Initialize();
    }

    private static void Initialize()
    {
        // Read the command line arguments
        string[] args = AppDomain.CurrentDomain.SetupInformation.ActivationArguments.ActivationData;

        if (args == null || args.Length == 0)
        {
            Application.Run(new Form1());
        }
        else
        {
            // Only attach the console when using the command line
            AttachConsole(ATTACH_PARENT_PROCESS);

            CmdLineHandler cmdLineObject = new CmdLineHandler(args[0].Split('!'));
        }
    }
}

So, as you can see, I’m PInvoking the console control (who doesn’t love a good pinvoke). In Initialize(), I’m checking to see if any args are being passed to the ClickOnce app using

AppDomain.CurrentDomain.SetupInformation.ActivationArguments.ActivationData;

This way I can start up the regular old forms app if no args are passed, or jump to the console app if there are. Then I’ve created a nice CmdLineHandler class to handle all the string parsing magic to make this work.

Here’s the important part, I’m serious, don’t skim over this part – you CANNOT use comma or space to separate your args when command-lining into a ClickOnce app. OK, I think I’ve bolded enough to make that stand out. For some reason, the comma in your args get’s swallowed. I’m not sure where it happens, but I know it happened every single time (I tried a bunch of different ways). Feel free to give it a try, hey, if you get it working, let me know!

OK, so I’m splitting those input args by !, which looks weird, but works fine. Once you’ve got the args, it’s up to you, I’m sure you’ll be fine.

Here’s the final command to my app

C:\Users\**YOU**\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\MyAwesomeApp -option1!yes!-option2!no

Again, I’m not endorsing ClickOnce, or this really, but if you’re stuck in this situation at work, this is my workaround.

Expression Trees

If you’re anything like me, you’re lazy.

I choose a lazy person to do a hard job. Because a lazy person will find an easy way to do it.

– Bill Gates

Apparently, in the world of programming, being lazy is a virtue, so maybe by passing this along I’m being virtuous?!?

I came across a library I had to implement this week that had function calls down to some hardware. Now since this library was a wrapper for a C (or C++) library, and whoever wrote it didn’t want to put a lot of work into it, every function called would return an ErrorCode enum.

Now if I was to be a copy and paste wizard, I’d just write myself about 20 of these

var errorCode = HARDWARE.GetSomeInformation(1, true, ref why???);

if (errorCode != ErrorCodes.None)
    Throw new CustomErrorException();

Obviously, that sucks. Nobody wants to do this. If you want to do this, you’re crazy. Even if you’ve got all the time in the world, or you’re a Regex master, or you’re using a tool called NimbleText you still shouldn’t do this. I think this is what people refer to as brittle code. If anything ever changes, or you realize you wanted to do something else with that error code, you’ve got to change it in 20 places (or more, how big is this library anyway?).

I decided to wrap this error call in a nice function delegate that would allow me to put all my ErrorCode handling in one place and just get on with stuff. Here’s what I ended up with

..
HARDWAREWrapper(() => HARDWARE.GetSomeInformation(1, true, ref why???));
..

private void HARDWAREWrapper(Func<ErrorCodes> functionToCall)
{
    var errorCode = functionToCall();

    if (errorCode != ErrorCodes.None)
        Throw new CustomErrorException();
}

OK, much better, now if anything in those function calls changes generically, or I decide to add more information to my exception we’re all good. It’s just one spot. Single responsibility principle? Not sure if that exactly counts, but my goal today is to sound smart by using lots of programming words (let me know how you think I’m doing).

So, here we go with the downside of this, since this is a generic call, it’s a little harder to figure out what exactly caused the exception in the first place. Since any code could be in that function (as long as it returns ErrorCodes) it’s a little harder to debug, especially if this is in the field and all.

Luckily I came across something pretty sweet called an Expression. I can wrap the Func<ErrorCodes> in this Expression to allow me access to the actual text of the function for debugging purposes. I’m sure that’s not what it was designed for, but it’s what I’m using it for today. Here’s the code –

..
HARDWAREWrapper(() => HARDWARE.GetSomeInformation(1, true, ref why???));
..

private void HARDWAREWrapper(Expression<Func<ErrorCodes>> expression)
{
    var functionToCall = expression.Compile();

    var errorCode = functionToCall();

    if (errorCode != ErrorCodes.None)
    {
        Logger.LogtoFile(expression.ToString();
        Throw new CustomErrorException();
    }
}

As you can see, the call to the function doesn’t actually change, even though it’s wrapped in an Expression, but it does allow you to log the function delegate contents to file. With Expression.ToString() I get access to the line HARDWARE.GetSomeInformation(1, true, ref why???) in text format.

Awesome. OK, that’s all I’ve got. If anyone out there is listening, let me know what you think!