October 20, 2014

Async/Await

Best explanation I have found
Looking underneath the hood
More complicated but diagrammed example here

The “async” keyword tells compiler that the method may return asynchronously, it enables the use of the await keyword. The beginning of an async method is executed just like any other method, it runs synchronously until it hits an “await” (or throws an exception).

The “await” keyword is where things can get asynchronous. Await is like a unary operator: it takes a single argument, an awaitable (an “awaitable” is an asynchronous operation). Await examines that awaitable to see if it has already completed; if the awaitable has already completed, then the method just continues running synchronously just like a regular method.

If “await” sees that the awaitable has NOT completed, then it acts asynchronously. It tells the awaitable to run the remainder of the method when it completes, and then returns from the async method.

Careful with a method that leaves a lot of data on the stack. This data will stay around until the async method is complete, ie all "async" tasks have completed.
private static async void DoSomethingAsync()
{
    var result = await SomeTask(args);
    DoSomethingWithResult(result);    
}

May 13, 2014

Searching for text within files using Linq

A good example of the power of Linq:
Directory.EnumerateFiles(@"S\Source\", "*.*proj", SearchOption.AllDirectories)
    .SelectMany(file => File.ReadAllLines(file).Select((text,n)=> new {text,lineNumber=n+1,file}))
    .Where(line => Regex.IsMatch(line.text,@"SccProjectName"))
    .Where(line => !Regex.IsMatch(line.text,@"SAK"))
    .Dump("Should be set to SAK")

February 18, 2014

Routing Events to Commands in WPF using MVVM Light

First reference some assemblies:
  • System.Windows.Interactivity
  • GalaSoft.MvvmLight.Extras.WPF4
In the XAML file add references to the namespaces in the window definition:
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:cmd="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.WPF4"
Within you window component, add the event to command handler's
<i:Interaction.Triggers>
    <i:EventTrigger EventName="Loaded">
        <cmd:EventToCommand Command="{Binding Mode=OneWay, Path=LoadedCommand}"
                        PassEventArgsToCommand="True" />
    </i:EventTrigger>
    <i:EventTrigger EventName="Closing">
        <cmd:EventToCommand Command="{Binding Mode=OneWay, Path=ClosingCommand}"
                        PassEventArgsToCommand="True" />
    </i:EventTrigger>
</i:Interaction.Triggers>
Then some code to process the command:
private RelayCommand<RoutedEventArgs> loadedCmd;

public RelayCommand<RoutedEventArgs> LoadedCommand
{
  get
  {
    return this.loadedCmd ?? (this.loadedCmd = new RelayCommand<RoutedEventArgs>
    ((rea) => 
    {
      // Use event argument 'rea' if you need it 
      // (but PassEventArgsToCommand="True" is needed in the Xaml, see above)
      this.ActivityText = "Copy files from \'" +
         m_AsyncPhotoBackup.TargetDirectory +
         "\' to \'" +
         m_AsyncPhotoBackup.DestinationDirectory +
         "\'.";
      m_AsyncPhotoBackup.RunWorkerAsync();
    }));
  }
}

TaskbarItemInfo in MVVM and Sample WPF Converter Usage

In this case we are using a WPF TaskbarItemInfo to show progress on an icon in the Taskbar. The taskbar progress value takes a double value between 0.0d and 1.0d. However, in this cae the progresss value is generated as an integer percentage between 0 and 100. So we create a converter class to convert our interger value between 0 and 100 to the double value. An alternative would be to create another property that creates the progress value in the appropriate form.
// Convert an integer percentage (0 to 100) to a double 
// between (0.0d and 1.0d)
public class IntPercentageToDoubleConverter : IValueConverter
{
    public object Convert(object value, Type targetType,
        object parameter, CultureInfo culture)
    {
        double res = 0.0d;
        if (value is int)
        {
            int intVal = (int)value;
            res = intVal / 100.0d;
            if (res < 0.0d)
                res = 0.0d;
            else if (res > 100.0d)
                res = 100.0d;
        }
        return res;            
    }

    public object ConvertBack(object value, Type targetType,
        object parameter, CultureInfo culture)
    {
        return null;
    }
}
In the Xaml we first need to create an instance of the converter. A few namespace declarations are required:
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:PhotoBackupApp.ViewModel"
Create the converter instance:
<Window.Resources>
    <local:IntPercentageToDoubleConverter x:Key="intPercentageToDoubleConverter" />
</Window.Resources>
Use the converter with the bound proprety
<Window.TaskbarItemInfo>
    <TaskbarItemInfo ProgressValue="{Binding Mode=OneWay, 
       Path=ProgressPercentage, 
       Converter={StaticResource intPercentageToDoubleConverter},
       UpdateSourceTrigger=PropertyChanged}" 
       ProgressState="Normal" />
</Window.TaskbarItemInfo>
The 2 important declarartions here are 'Path=ProgressPercentage, Converter={StaticResource intPercentageToDoubleConverter},'. This is the property to bind to and the converter instance to use.

Closing a Dialog Window in WPF using MVVM

Alot of ideas are mentioned on this website:
http://stackoverflow.com/questions/4376475/wpf-mvvm-how-to-close-a-window

Simplest way is to simply define the close button as normal using the click event
<Button Content="OK" IsDefault="True" Click="okButton_Click" />
Here is the code behind:
private void okButton_Click(object sender, RoutedEventArgs e)
{
 this.Close();
}
This does not affect the ViewModel in any way, the ViewModel knows nothing about the close functionality. and there is nothing wrong with code behind if it does not affect the ViewModel.
However I wanted to be able to initiate the Close from the ViewModel. To do this I defined a property that takes a simple Action delegate
public Action CloseAction { get; set; }
In the constructor I give it a default value
this.CloseAction = () => 
    { Debug.WriteLine("ActivePhotoBackupViewModel - Close Action Undefined"); )};
Now I can use a command to perform the CloseAction
#region Done Command
private RelayCommand doneCommand;

public RelayCommand DoneCommand
{
 get
 {
  return this.doneCommand ?? 
    (this.doneCommand = new RelayCommand(() => 
     {
      DoSomeOtherStuffHere();
      this.CloseAction();
     }
    ));
 }
}
#endregion Done Command
When creating the view model the close action is defined:
...
ActivePhotoBackupViewModel vm = new ActivePhotoBackupViewModel(srcDir, destDir, photoBackupOptions);
PhotoBackupDlg photoBackupDlg = new PhotoBackupDlg();
vm.CloseAction = new Action(() => photoBackupDlg.Close());
...
Could have a used an interface here on a class to perform the same work but then the interface would have had one method so it is simpler just to use a delegate instead ('Action' is a system defined delegate). Also there were no future extra requirements envisaged on this interface (otherwise the interface route would have been worth it). This simple solution does not impede any unit testing of the ViewModel either.

November 26, 2013

Working with SandCastle Problems

I created a project using the "SHFB v1.9.7.0 with Visual Studio Package". This was used to convert an old help project to the latest format. However after the conversion I had make 2 fixes to get the project to build. SandcastleHelpBuilder post conversion fixes:
  1. Ensure that in the "Project Properties" tab 'Build' option that the 'Framework Version' field is set to '.NET Framework 2.0', the framework version of the compiled source code.
  2. Ensure that in the "Project Properties" tab 'Paths' option that the 'Working files path' field is set to 'Working\'.

November 6, 2013

Path Extension Class

This helper creates a temporary file with the given extension.
public static class PathExtensions
{
 // Create a temporary file with a specific file extension
 public static string GetTempFileName(string extension)
 {
  string tempFileName = Path.GetTempFileName();
  string newtempFileName = tempFileName.Replace(".tmp", extension);
  File.Move(tempFileName, newtempFileName);
  return newtempFileName;
 }
}