Why you need to learn async in .NET

I had an opportunity to teach a quick class yesterday about what’s new in .NET 4.0.  One of the topics was the TPL (Task Parallel Library) and how it can make async programming easier.  I also stressed that this is the direction Microsoft is going with for C# 5.0 and learning the TPL will greatly benefit their understanding of the new async stuff.  We had a little time left over and I was able to show some code that uses the Async CTP to accomplish some stuff, but it wasn’t a simple demo that you could jump in to and understand so I thought I’d thrown one together and put it in a blog post.

The entire solution file with all of the sample projects is located here.

A Simple Example

timerform

Let’s start with a super-simple example (WindowsApplication01 in the solution). I’ve got a form that displays a label and a button.  When the user clicks the button, I want to start displaying the current time for 15 seconds and then stop. What I’d like to write is this:

lblTime.ForeColor = Color.Red;
for (var x = 0; x < 15; x++)
{
    lblTime.Text = DateTime.Now.ToString("HH:mm:ss");
    Thread.Sleep(1000);
}
lblTime.ForeColor = SystemColors.ControlText;

(Note that I also changed the label’s color while counting – not quite an ILM-level effect, but it adds something to the demo!)

As I’m sure most of my readers are aware, you can’t write WinForms code this way.  WinForms apps, by default, only have one thread running and it’s main job is to process messages from the windows message pump (for a more thorough explanation, see my Visual Studio Magazine article on multithreading in WinForms).  If you put a Thread.Sleep in the middle of that code, your UI will be locked up and unresponsive for those 15 seconds.  Not a good UX and something that needs to be fixed.  Sure, I could throw an “Application.DoEvents()” in there, but that’s hacky.

The Windows Timer

Then I think, “I can solve that.  I’ll use the Windows Timer to handle the timing in the background and simply notify me when the time has changed”.  Let’s see how I could accomplish this with a Windows timer (WindowsApplication02 in the solution):

public partial class Form1 : Form
{
    private readonly Timer clockTimer;
    private int counter;
 
    public Form1()
    {
        InitializeComponent();
        clockTimer = new Timer {Interval = 1000};
        clockTimer.Tick += UpdateLabel;
    }
 
    private void UpdateLabel(object sender, EventArgs e)
    {
        lblTime.Text = DateTime.Now.ToString("HH:mm:ss");
        counter++;
        if (counter == 15)
        {
            clockTimer.Enabled = false;
            lblTime.ForeColor = SystemColors.ControlText;
        }
    }
 
    private void cmdStart_Click(object sender, EventArgs e)
    {
        lblTime.ForeColor = Color.Red;
        counter = 0;
        clockTimer.Start();
    }
}

Holy cow – things got pretty complicated here.  I use the timer to fire off a Tick event every second.  Inside there, I can update the label.  Granted, I can’t use a simple for/loop and have to maintain a global counter for the number of iterations.  And my “end” code (when the loop is finished) is now buried inside the bottom of the Tick event (inside an “if” statement).  I do, however, get a responsive application that doesn’t hang or stop repainting while the 15 seconds are ticking away.

But doesn’t .NET have something that makes background processing easier?

The BackgroundWorker

Next I try .NET’s BackgroundWorker component – it’s specifically designed to do processing in a background thread (leaving the UI thread free to process the windows message pump) and allows updates to be performed on the main UI thread (WindowsApplication03 in the solution):

public partial class Form1 : Form
{
    private readonly BackgroundWorker worker;
 
    public Form1()
    {
        InitializeComponent();
        worker = new BackgroundWorker {WorkerReportsProgress = true};
        worker.DoWork += StartUpdating;
        worker.ProgressChanged += UpdateLabel;
        worker.RunWorkerCompleted += ResetLabelColor;
    }
 
    private void StartUpdating(object sender, DoWorkEventArgs e)
    {
        var workerObject = (BackgroundWorker) sender;
        for (int x = 0; x < 15; x++)
        {
            workerObject.ReportProgress(0);
            Thread.Sleep(1000);
        }
    }
 
    private void UpdateLabel(object sender, ProgressChangedEventArgs e)
    {
        lblTime.Text = DateTime.Now.ToString("HH:mm:ss");
    }
 
    private void ResetLabelColor(object sender, RunWorkerCompletedEventArgs e)
    {
        lblTime.ForeColor = SystemColors.ControlText;
    }
 
    private void cmdStart_Click(object sender, EventArgs e)
    {
        lblTime.ForeColor = Color.Red;
        worker.RunWorkerAsync();
    }
}

Well, this got a little better (I think).  At least I now have my simple for/next loop back.  Unfortunately, I’m still dealing with event handlers spread throughout my code to co-ordinate all of this stuff in the right order.

Time to look into the future.

The async way

Using the Async CTP, I can go back to much simpler code (WindowsApplication04 in the solution):

private async void cmdStart_Click(object sender, EventArgs e)
{
    lblTime.ForeColor = Color.Red;
    for (var x = 0; x < 15; x++)
    {
        lblTime.Text = DateTime.Now.ToString("HH:mm:ss");
        await TaskEx.Delay(1000);
    }
    lblTime.ForeColor = SystemColors.ControlText;
}

This code will run just like the Timer or BackgroundWorker versions – fully responsive during the updates – yet is way easier to implement.  In fact, it’s almost a line-for-line copy of the original version of this code.  All of the async plumbing is handled by the compiler and the framework.  My code goes back to representing the “what” of what I want to do, not the “how”.

I urge you to download the Async CTP.  All you need is .NET 4.0 and Visual Studio 2010 sp1 – no need to set up a virtual machine with the VS2011 beta (unless, of course, you want to dive right in to the C# 5.0 stuff!).  Starting playing around with this today and see how much easier it will be in the future to write async-enabled applications.

Posted by PSteele | 2 comment(s)
Filed under: , ,

Using hg bisect to hunt down bugs

The “bisect” command in Mercurial (git has it too) is a great way to quickly find which version of your code introduced a bug.  This post will show you how to use the bisect command along with handling a small “gotcha” I encountered while using it.

I recently had to hunt down a bug in a very old version of an application.  While the application had gone through numerous releases after the bug had been introduced, nobody had noticed.  And as luck would have it, this particular bug was also in a section of code without unit tests – I’d have to load up the code in Visual Studio and run the app to verify the bug.  Since I tag each revision in Mercurial that is used to produce a release, I knew which revision the users first noticed the bug – and I knew the previous release didn’t have the bug.  The problem was that between the bad release and the good release was about 26 commits.  I used Mercurial’s bisect command to make locating the bug quicker.

The first thing to do when doing a bisect is to ensure your working directory has no uncommitted changes.  The bisect command will perform an hg update automatically as it helps you zero in on the bug so it’s important you don’t have any uncommitted code.

Next, I went to my working directory and initialized the bisect operation by running:

hg bisect –r

Now, I had to tell bisect which version was bad (where I knew the bug exists) and which version was good (where I know the bug does not exist).  In this case, revision 581 was good and revision 606 was bad:

hg bisect –g 581
hg bisect –b 606

Mercurial responded:

Testing changeset 593:e3c0018aef4d (25 changesets remaining, ~4 tests)
37 files updated, 0 files merged, 23 files removed, 0 files unresolved

Mercurial had immediately updated my working directory to revision 593. This revision is about halfway between the good revision and the bad revision.  Here’s a graphical view of what I told Mercurial:

bisec01

I opened Visual Studio to load the project up and test the application.  I only have Visual Studio 2010 installed and this was a Visual Studio 2008 solution (see, I told you it was old).  I let Visual Studio perform the conversion.  I then ran the app and found that the bug exists in this version.  At this point, I needed to tell Mercurial that this version was bad.  At the command prompt I entered:

hg bisect –b

Mercurial’s response was an error:

Testing changeset 587:d6e96f87a104 (12 changesets remaining, ~3 tests)
abort: outstanding uncommitted changes

Since 593 was now the first bad revision, Mercurial tried to update to a version between 593 and 581 but couldn’t because there were uncommitted changes.  Remember how I said this an old VS2008 solution?  Since I upgraded it to VS2010, the solution was changed and Mercurial stopped the automatic update that the bisect command wanted to do.

For this situation, I didn’t care about the change to my working directory.  So I had to revert all of the changes before I could continue with the bisect:

hg revert –a
hg bisect –b

Now the bisect worked and put me at revision 587, which is just about right in between the last known good version and the last known bad version:

bisect02

Testing this version in VS2010 (again, the VS2008 solution was updated to 2010), I found the bug didn’t exist.  So I went back to my command prompt, reverted my changes and marked this version as good:

hg revert –a
hg bisect –g

 

bisect03

I was getting closer!  I’m now at revision 590 and the bug still existed.  I revert and mark it as bad:

hg revert –a
hg bisect –b

 

bisect04

After this, Mercurial updated my working directory to revision 588.  I tested it and found the bug.  I did my revert and marked it bad:

hg revert –a
hg bisect –b

Mercurial now reports 588 as the first revision where the bug appeared (since 587 was already marked good).

The bisect command is very useful for quickly hunting down bugs.  In this case, it took a little longer since I had to load the code up into Visual Studio (and convert it), run the code and then revert my changes afterward.  If the code didn’t need to be converted and had a full set of unit tests, identifying the revision where the bug first appeared would have been even quicker.  In fact, the whole process can be automated with the “-c” option which allows you tell Mercurial the name of the command to run to validate the revision!

Technorati Tags: ,,
Posted by PSteele | 1 comment(s)
Filed under: ,

2012 Begins

It has become tradition for the past few years that my first blog post of the new year is to thank Microsoft for being recognized as an MVP.  This year is no different.  Once again, I’m honored to be recognized by Microsoft for my contributions to the community.  After visiting Redmond for the past 4 years, I’m going to be skipping the Summit this year.  I’ve got a client project that I really want to focus on and don’t want to push it out another week.

For 2012, I’ll continue to produce C# Corner articles for Visual Studio Magazine.  A big thanks to Eric Vogel who took over the web-only side of the C# Corner.  Between work, the print version of C# Corner and various family commitments, I could not continue producing the additional web-only articles.  I talked it over with my editor, Michael Desmond and he was totally understanding and found Eric to help me out.  Thanks Eric!

My interest in Android has not abated.  I’m still writing apps here and there for the platform.  I recently started looking in to the “android-binding” project (data binding for MVVM/MVP style apps) as well as “roboguice” (dependency injection for Android).  Both look like some really neat projects that will make developing Android apps easier.

After coming back from CodeMash 2012, I’m excited at the opportunity to implement some of what I learned.  If you have the opportunity to go to CodeMash, I urge you to attend!  Just be fast – this year, CodeMash sold out 1200 tickets in only 20 minutes!  Once you’ve attended one, you’ll know why!

Posted by PSteele | 1 comment(s)
Filed under: , , ,

Using WPF Converters to Affect Multiple Properties

I’m working on my first WPF application.  I’ve done a ton of reading on WPF and it’s helped me in my understandings of how WPF works.  So far, I’m really liking the data binding flexibility WPF gives you.  That, along with a very testable MVVM-based architecture, has made the experience a fun one!

Yesterday, I came across a situation where I needed a single item from my view model (an enum value) to affect two properties on a  WPF element (the Foreground and Background colors of a DataGridCell).  I’m familiar with value converters, but they only convert to a single value.  I did some research on MultiValueConverters, but, as seasoned WPF developer Anne Marsan pointed out, they take multiple inputs but still only produce a single output.  How to proceed?

NOTE: I’ve provided sample code in a BitBucket project here.  Each “attempt” that I detail below is tagged in the repository so you can easily see the implementations of each approach by switching your working directory to a certain tag.

First Attempt (Tag: Attempt1)

My first attempt was brute force and worked, but was messy – I simply created two value converters: both would take my enum, but one would return the background color and one would return the foreground color.

[ValueConversion(typeof(CompareResult), typeof(String))]
class ForeColorConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var result = (CompareResult)value;
        var ci = ColorInformation.FromResult(result);
        return ci.ForeColor;
    }
 
    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return null;
    }
}
 
[ValueConversion(typeof(CompareResult), typeof(String))]
public class BackColorConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var result = (CompareResult)value;
        var ci = ColorInformation.FromResult(result);
        return ci.BackColor;
    }
 
    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return null;
    }
}
<Style TargetType="{x:Type DataGridCell}">
    <Setter Property="Background" Value="{Binding CompareResult, Converter={StaticResource BackColorConverter}}"></Setter>
    <Setter Property="Foreground" Value="{Binding CompareResult, Converter={StaticResource ForeColorConverter}}"></Setter>
</Style>

This was too much code duplication and I didn’t like it.  But, I kept it around it as my fallback measure if I couldn’t find a more elegant solution.

Second Attempt (Tag: Attempt2)

Why mess with converters?  Why not just expose the ForeColor and BackColor as properties on my view model.  Simple data binding would make this effortless.

<Style TargetType="{x:Type DataGridCell}">
    <Setter Property="Background" Value="{Binding ForeColor}"></Setter>
    <Setter Property="Foreground" Value="{Binding BackColor}"></Setter>
</Style>

But I didn’t like this idea – it sounds too much like I’m mixing my UI and my view model.  The view model (in my opinion) should just represent the data to be displayed.  It’s up to the view to decide how this data should be displayed.

Third Attempt (No Tag)

Before I had talked with Anne Marsan about the MultiValueConverters, I thought about creating a multivalue converter that would take both the framework element I want to affect as well as my enum value and do the property setting right inside the converter.  This was too complicated and it would have limited my converter to only working against a certain framework element (a DataGridCell in this case).  I never did any coding for this and therefore there is no “Attempt3” tag.

Final Solution (Tag: Attempt4)

Then I learned about the ConvertParameter.  This allows you to pass an additional parameter to an IValueConverter.  I decided I could pass in a flag to indicate whether I wanted the foreground color or the background color.

[ValueConversion(typeof(CompareResult), typeof(String))]
public class ColorInformationConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var result = (CompareResult)value;
        var ci = ColorInformation.FromResult(result);
        return parameter.ToString().Equals("forecolor", StringComparison.CurrentCultureIgnoreCase)
                ? ci.ForeColor
                : ci.BackColor;
    }
 
    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return null;
    }
}
<Style TargetType="{x:Type DataGridCell}">
    <Setter Property="Background" Value="{Binding CompareResult, Converter={StaticResource ColorConverter}, ConverterParameter='backcolor'}"></Setter>
    <Setter Property="Foreground" Value="{Binding CompareResult, Converter={StaticResource ColorConverter}, ConverterParameter='forecolor'}"></Setter>
</Style>

This solutions gets me to a single converter, is relatively clean in the XAML (I think) and doesn’t pollute my view model with view concerns.

At the end of August, I’ll be attending a ZeroToSilverlight training session and hope to learn more about doing these types of things in XAML.  Perhaps I’ll revisit this post if I find a better way to do this.  Is there a better way to do this?  Comments welcomed.

Technorati Tags: ,
Posted by PSteele | 2 comment(s)
Filed under: , ,

Published My First Android Application!

While I’ve been playing around with Android development for a few months and I’ve started half-a-dozen various apps, I finally completed one and submitted it to the Android Market.  It’s a simple SQLite database app that contains the 2011 ferry schedule for the Star Line Mackinac Island Ferry.

Starline publishes a PDF with their complete schedule and it’s sitting in one of my Dropbox folders.  But viewing the schedule meant I had to open Dropbox, navigate to the folder then click on the PDF to download it. Then wait for the PDF to appear and navigate to the schedule and pinch/zoom to find the date range I’m looking for.

With my application, you simply pick your dock and then click on handy “Today” or “Tomorrow” buttons which will automatically calculate which date range you fall in.  Then you’ll get a listing of departure times both from the mainland and from the island.  You’re also free to pick any of the published date ranges to see times for the entire regular season.

If you’re planning a trip to Mackinac Island and plan to take the Star Line ferry, it’s a nice way to keep the schedule with you at all times.

Posted by PSteele | 2 comment(s)
Filed under:

Taking Android Emulator Screenshots WITHOUT Eclipse.

I’m working on an Android app and before publishing it to the Android Market, I needed some screenshots.  I assumed the emulator supported screenshots, but when I did a search for “android emulator screenshot”, most of the hits talked about how to do it from Eclipse.  I’m using IntelliJ IDEA Community Edition.  However, based on the descriptions, I understood what was going on.

The Eclipse plugin is talking to the emulator directly.  If you want to do that outside of Eclipse, you can do it using ddms – the Dalvik Debug Monitor.  Go to your Android SDK directory and look in the “tools” directory.  Run the “ddms.bat” file.  This will launch the Dalvik Debug Monitor.

image

From here, getting screenshots is easy.  Select the emulator that is currently running (in my case, “emulator-5556”).  Now start the screenshot application by either going to the “Device” menu and selecting “Screen capture…” or simply pressing CTRL+S.

image

Go back to the emulator, do whatever it is you need to do and when you’re ready for a screenshot, go back to the Device Screen Capture window and click “Copy” to save the screenshot to the clipboard or “Save” to open up a file browser where you can pick the location to save your image.  If you need more images, go back to the emulator, go to your next view/screen/whatever and then return to the Device Screen Capture window and click “Refresh” to update the image.

Posted by PSteele | with no comments
Filed under:

HOWTO: Change which “.testsettings” file Visual Stuido 2010 uses

I’m blogging this mainly for historical reasons.  I just spent over 30 minutes trying to figure this out.  Well, the first 10 or 15 minutes was getting code coverage enabled in Visual Studio 2010.  There’s plenty of coverage on that topic since it’s not as intuitive as it could be.  I’ll let Google handle that one.

Visual Studio 2010 allows you to create multiple “testsettings” files in your solution.  This allows you to set up customized configurations to control deployment, code coverage and a ton of other settings.  My solution has two settings (I think these are the defaults): “Local.testsettings” and “TraceAndTestImpact.testsettings”.  I configured Code Coverage in my “local” test settings.  I then ran my unit tests and went to check out the code coverage.

Visual Studio told me there was no code coverage data available – and prodded me to check the test results for errors.  I looked at the test results and didn’t see any errors but I did notice one thing.  The “Results Summary” for my test run displayed:

Test settings: TraceAndTestImpact

Ah ha!  So it’s not using my Local settings.  All I need to do is tell the unit tests to run with the “local”  testsettings file and I’ll be all set.  But how do I do that?  A few Google searches didn’t reveal much.  I finally (out of desperation), checked the ol’ drop down menus.  Under “Test” there is an option called “Select Active Test Settings”.  Under there, you can pick which settings file to use.

 

image

Posted by PSteele | 1 comment(s)

WPF: Simple “Busy” Overlay

I’m working on a WPF project that does some background processing which could take more than a few seconds.  Instead of a busy cursor, I want to give the user a simple “Please wait…” message via an overlay that appears on top of the form.  I found the solution in this stackoverflow question.  However, the solution presented there was an overview.  In this post I’ll show a complete example along with a downloadable sample project so you can play with it for yourself.

Disclaimer

First, a disclaimer: I’m currently working on my very first WPF application.  There may be an easier way to do this, but in building this solution from the stackoverflow question, it seemed pretty simple to me (hence the title).  Also, this form was using a Grid for layout.  I would think the general approach I use should work for other layouts, but I’ve only ever used this technique in a grid.

This sample project is done using the MVVM pattern.  If you’re not familiar with this pattern, don’t worry.  This example is pretty straightforward so you should be able to get the general idea.  Also, if you’re using the MVVM pattern with your WPF (or Silverlight) apps, you should strongly consider using Simon Cropp’s Notify Property Weaver.  This little tool allows you to write regular auto-properties in your view models and it will “weave” the required IL into the generated property getters and setters to handle the INotifyPropertyChanged interface.  Highly recommended! 

Initial Window

Let’s start with a very simple window:

image

This form collects a couple of pieces of information and has a link button to start the process.  The entire view model to run this form is show here (see Google and/or the source code if you need more information on the DelegateCommand):

public class BusyViewModel : INotifyPropertyChanged
{
    private ICommand doSomethingCommand;
 
    public event PropertyChangedEventHandler PropertyChanged;
 
    public string Item1 { get; set; }
    public string Item2 { get; set; }
    public List<String> Results { get; set; }
 
    public ICommand DoSomething
    {
        get { return doSomethingCommand ?? (doSomethingCommand = new DelegateCommand(LongRunningTask)); }
    }
 
    private void LongRunningTask()
    {
        var results = Enumerable.Range(0, 12).Select(x =>
                                        {
                                               Thread.Sleep(250);
                                               return "Result " + x;
                                        }).ToList();
        this.Results = results;
    }
}

 

If you clone my repository to your local machine and update your working directory to RevID 0 (the initial commit) you can run the app and see how clicking on the “DoSomething” link initiates the ICommand which runs a simple LINQ query to build up the sample results.  I stuck a Thread.Sleep in there to simulate load.  As a result, the window is unresponsive for about 3 seconds.  Let’s add a simple overlay to let the user know the application is busy.

Improved UI

First off, we want our view model to expose an “IsBusy” flag to indicate that it is busy doing something.  This is as easy as adding a property:

public bool IsBusy { get; set; }

And then we’ll put our long-running process into a background Task which will set the IsBusy flag when it starts and reset it when complete:

private void LongRunningTask()
{
    var task = new Task(ComputeResults);
    task.Start();
}
 
private void ComputeResults()
{
    this.IsBusy = true;
    var results = Enumerable.Range(0, 12).Select(x =>
                                                    {
                                                        Thread.Sleep(250);
                                                        return "Result " + x;
                                                    }).ToList();
    this.Results = results;
    this.IsBusy = false;
}

That’s all we need to do in the view model.  See how nice the MVVM pattern is?

From the UI side of things, we need to add our busy overlay.  Right before the closing </Grid> tag, I added a border and gave it a Grid.RowSpan of 3 (there’s three rows in my grid so this covers the entire grid):

<Border BorderBrush="Black" BorderThickness="1" Background="#80000000" Visibility="Collapsed" Grid.RowSpan="3">
    <Grid>
        <TextBlock Margin="0" TextWrapping="Wrap" Text="Please Wait..." HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="24" FontWeight="Bold" Foreground="#7EFFFFFF"/>
    </Grid>
</Border>

The Visibility of the Border is set to “Collapsed” which means it takes up no space and is invisible.  We’ll want that to change based on our view model’s IsBusy flag.  While data binding will work, we have to remember that we can’t directly bind a boolean type (IsBusy) to a Visibility type.  We’ll need to create an IValueConverter which can convert a boolean to a Visibility value.  I’ve named mine “BoolToVisibilityConverter”:

public class BoolToVisibilityConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        try
        {
            var v = (bool) value;
            return v ? Visibility.Visible : Visibility.Collapsed;
        }
        catch (InvalidCastException)
        {
            return Visibility.Collapsed;
        }
    }
 
    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

Since we’re not doing 2-way binding, we don’t need to implement the ConvertBack method.  With the converter coded, we need to tell the WPF window how to use this converter when binding the Visibility attribute of the Border to the IsBusy value on the view model.

First, we’ll add a namespace to the main <Window> tag that points to the namespace where our converter exists:

xmlns:conv="clr-namespace:SampleBusyOverlay"

And then we can add a resource to the window pointing to our converter:

<Window.Resources>
    <conv:BoolToVisibilityConverter x:Key="boolConverter"/>
</Window.Resources>

Now we can bind the Border’s Visibility attribute to the view model’s IsBusy flag using the converter:

<Border BorderBrush="Black" BorderThickness="1" Background="#80000000" Visibility="{Binding IsBusy, Converter={StaticResource boolConverter}}" Grid.RowSpan="3">
    <Grid>
        <TextBlock Margin="0" TextWrapping="Wrap" Text="Please Wait..." HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="24" FontWeight="Bold" Foreground="#7EFFFFFF"/>
    </Grid>
</Border>

That’s it!  Update your working copy to RevID 1. If you re-run the project now, you’ll see a nicer UI letting the user know the application is busy doing something:

image

The source for this sample can be found in my Bitbucket repository SampleBusyOverlay.

Technorati Tags: ,,
Posted by PSteele | with no comments
Filed under:

Clarification on Updating DefaultLocation in an MSI

Back in February, I did a blog post on how to change the default location for an Application installed via an MSI.  Thanks to a comment from Joe Marcelino, it wasn’t clear where to find the “DefaultLocation” field to change that.  Here’s a quick how-to on finding the field.

1. Right-click on your Setup project in Solution Explorer and select “View” and then “File System”:

Step1

2. In the window that opens up, under “File System on Target Machine”, select “Application Folder”:

Step2

3. Now, look at the “Properties” window and you’ll see the DefaultLocation property:

Step3

Now you can use any of the settings defined in MSDN to change where the application is installed.

Technorati Tags: ,
Posted by PSteele | 1 comment(s)
Filed under:

Android: Encapsulating Shared Preferences

The Android OS gives you a convenient way to save and load simple data (i.e. string, float, int, boolean and long) in the form of SharedPreferences.  The data is stored in a dictionary format that utilizes a key/value pair.  The “name” of the preferences is also supplied by your code.  In a lot of the samples you’ll find online, the name of the shared preferences and all of the keys are stored as constants at the top of the Activity class (or worse, the key names are copy/pasted throughout the code!).  I don’t like polluting my Activity classes with stuff like that so I’ve been encapsulating my preferences in their own class.

Here’s a simple preferences class that exposes a couple of pieces of data – Full name and Age:

package com.example;
 
import android.content.Context;
import android.content.SharedPreferences;
 
public class AppPrefs
{
    private final static String ACCOUNT_PREFS_NAME = "prefs";
    private final static String FULLNAME_KEYNAME = "FULLNAME_KEY";
    private final static String AGE_KEYNAME = "AGE_KEY";
 
    private final Context context;
    private String fullName;
    private int age;
 
    public AppPrefs(Context ctx)
    {
        this.context = ctx;
        SharedPreferences prefs = context.getSharedPreferences(ACCOUNT_PREFS_NAME, Context.MODE_PRIVATE);
        fullName = prefs.getString(FULLNAME_KEYNAME, "unknown");
        age = prefs.getInt(AGE_KEYNAME, 18);
    }
 
    public String getFullName()
    {
        return fullName;
    }
 
    public void setFullName(String name)
    {
        fullName = name;
    }
 
    public int getAge()
    {
        return age;
    }
 
    public void setAge(int number)
    {
        age = number;
    }
 
    public void Save()
    {
        SharedPreferences prefs = context.getSharedPreferences(ACCOUNT_PREFS_NAME, Context.MODE_PRIVATE);
        SharedPreferences.Editor edit = prefs.edit();
        edit.putString(FULLNAME_KEYNAME, fullName);
        edit.putInt(AGE_KEYNAME, age);
        edit.commit();
    }
}

You can see it’s a very simple class, but it hides all the key names within the class.  The main consumer of this class doesn’t need to know the name of the keys or even how the data is stored.  By simply using the get/set methods and the Save() method, the Activity can concentrate on what it was designed to do.  Imagine if we need to change where we’re storing the data?  Maybe we’re moving from SharedPreferences to a SQLite database?  In that case, we simply change the preferences class and the Activity won’t need any modifications.

I haven’t done a lot of Android programming yet, but so far, this technique has been working out well.  I’ve created a sample application based on IntelliJ IDEA 10 using this technique on my bitbucket account.

Technorati Tags: ,
Posted by PSteele | with no comments
Filed under: ,
More Posts Next page »