Resolution Independent WPF Apps

Working with aging hardware is tough.

For the last couple of years I’ve been working for a manufacturing company, creating a new application that would instruct the operators on the manufacturing line on how to assemble the hardware.

It needs to be really clear, and due to the amount of information they need, the UI is pretty full, with every square inch used up with “high-priority” information. The old version of this app was written in VB6, and the new in WPF.

Luckily, my managers have been on board with me buying new hardware for the manufacturing lines, so I’ve been able to use shiny new PCs with nice 1080p monitors for the operators on the line. Perhaps I’ve been spoiled by my years in software development, because I’d kind of forgotten that people have monitors that are not 1920×1080. I’m used to reading about specs for brand new laptops that are now pushing 4k.

Unfortunately, these brand new computers are not the only place I have to deploy my app. It turns out people want this to run on their desk PCs, which brings me back around to this; working with aging hardware is tough.

More recently I’ve started deploying my app in person to these plants around the country, and I’ve found I’m much more likely to find one of these

crap pc

Than one of these

nice pc

Now, you may be asking, what kind of resolution does one of these lovely PCs provide? Well, it turns out, it can range, quite significantly. It’s almost definitely not 1080p, but I’m fairly sure I’ve stumbled across an 800 x 600 monitor buried underneath an inch of dust. You can see my dilemma here.

Now, this shouldn’t be a problem, Microsoft claims WPF is resolution independent. In theory, I guess it is, but I’ll let StackOverflow explain my problem.

resolution independent

So it will adapt your screen to the resolution. The problem comes when you’re using a large size 20 font for a title. In 1080p it all looks totally reasonable, but down in 800 x 600, it takes up 1/4 of the screen. It still shows everything, but not in any kind of human-usable way.

Obviously this won’t work.

To fix this problem, I created a panel called ResolutionIndependentPanel. It’s pretty simple, I basically take a ScaleTransform and scale the entire contents of the panel based on the resolution of the screen it’s being displayed on. You supply it with the resolution you designed it on, in this case it’s 1920×1080, but it could be anything, and it figures out if it needs to up or downscale to make it look pretty similar in any resolution.

The goal is to end up with the same usable space. If your textbox took up 10% of the screen on the “designed” resolution, then it should take up that same 10% on an 800×600 monitor. Here’s a screenshot to give you an idea of what I’ve done here

panel comparison

As you can see, they have the same proportional layout and if you were to look at this on an 800×600 monitor, everything would look pretty normal.

OK, that’s basically all it does, I’m a big fan of simple fixes, and I’m going to be rolling out this one in my app this week, so I thought I’d share. It’s available in NuGet for .NET 4+, just search for ResolutionIndependentPanel.

To use it, just set up the namespace in the declarations of your UserControl or Window and wrap all your content inside of the ResolutionIndependentPanel. DesignHeight and DesignWidth have to be set to your design resolution. Piece of cake, right?

...
xmlns:rip="clr-namespace:ResolutionIndependentPanel;assembly=ResolutionIndependentPanel"
...

<rip:ResolutionIndependentPanel DesignHeight="1080"
                                DesignWidth="1920">
    <Grid>{ Your Content }</Grid>
</rip:ResolutionIndependentPanel>

 

Be careful with the scaling though. There are some known pitfalls. If you are a big fan of modern design, you might be using the built-in drop shadow effects. Well, unfortunately, these do something weird to the scale transforms. I think what’s happening is that WPF is taking a bitmap of the control and scaling that, instead of scaling it as a vector. Something like that, but you end up with blurry text and controls. In this case, maybe try and create your own drop shadows (I made mine out of Rectangles) to workaround it.

Links

https://github.com/chris84948/ResolutionIndependentPanel

https://www.nuget.org/packages/ResolutionIndependentPanel

P.S. If you think this is helpful, check out my other simple WPF panel fix, AirspaceFixer, it’s also available in Nuget and is based on a GitHub project.

https://github.com/chris84948/AirspaceFixer

Advertisements

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.

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.

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!

Visual studio snippets

I only recently graduated from part-time coder to full-time coder. My previous job was part engineer, part programmer, so I never really spent enough time looking into some of the nicer features of Visual Studio.

Luckily, that’s all changed now. Snippets have by far become my favorite coding shortcut. At first, I didn’t think I had much use for it. If I had to create a long chunk of code I’d just revisit an older project and copy it over, no problems right? Well, now that I’m always coding I see what a waste of time that was.

I’m sure you can find out how to do these just about anywhere, in fact, I’m certain MSDN has a nice section on it, but I’m going to run you through it all the same.

Here’s my favorite snippet, it’s for an IConverter to be used in your xaml. These always have exactly the same starting point, so they’re perfect.

Step one is create a new file with the extension .snippet. In this case, I named it IConverter.snippet.

Now copy all the following code into it and I’ll go through it step by step. I’ve highlighted all the sections you’ll want to change.

<?xml version="1.0" encoding="utf-8"?>
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
  <CodeSnippet Format="1.0.0">
    <Header>
      <SnippetTypes>
        <SnippetType>Expansion</SnippetType>
      </SnippetTypes>
      <Title>**Converter**</Title>
      <Author>**YourName**</Author>
      <Description>
      </Description>
      <HelpUrl>
      </HelpUrl>
      <Shortcut>**SnippetShortcut**</Shortcut>
    </Header>
    <Snippet>
        <Declarations>
            <Literal>
                <ID>**type1**</ID>
                <Default>**double**</Default>
            </Literal>
            <Literal>
                <ID>**type2**</ID>
                <Default>**double**</Default>
            </Literal>
            <Literal>
                <ID>**class**/ID>
                <Default>**___Converter**</Default>
            </Literal>
        </Declarations>
        <Code Language="csharp"><![CDATA[**[ValueConversion(typeof($type1$), typeof($type2$))]
    public class $class$ : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (!(value is $type1$))
                return 0;


        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
    **$end$]]>
            </Code>
    </Snippet>
  </CodeSnippet>
</CodeSnippets>

OK, it’s pretty straightforward from here. Give the snippet a Name and Author, although they don’t really matter too much. More importantly, replace SnippetShortcut with something useful, in my case I used conv. This is the shortcut you’ll use in Visual Studio to run the snippet. All you need to do it type conv[TAB][TAB] and you’re up and running.

In the declarations section,

<Declarations>
    <Literal>
        <ID>**type1**</ID>
        <Default>**double**</Default>
    </Literal>
</Declarations>

You can declare all the variables in your code snippet, with an ID and Default Value. The ID can be used in the codeblock below. You have to surround the ID in $, like this $type1$ for the snipper to find and replace it correctly. The default value should be something sensible. I like to try and make that a useable value, so if I forget what that should be, the default gives me a hint.

Finally, replace the section that is highlighted bold (don’t delete the [CDATA[ or $end$ sections or it’ll break). Make sure to replace any section that might be a variable in your code block with the correct $variablename$.

OK, so you’re all done, now what? Well, open up Visual Studio, goto Tools —> Code Snippets Manager, click Add and locate your snippet folder. That’s it.

Now, after all that hard work you can relax and enjoy the beauty of code snippets.