Wednesday, December 09, 2009

One More Reason To Hate DOS Command

Today one of my command script starts to fail mysteriously. I had run it many times before. The failing fragment seems to be like this:

if Exist "%ProgramFiles(x86)%\Microsoft Visual Studio 10.0" (
    Set VS10=%ProgramFiles(x86)%\Microsoft Visual Studio 10.0
)

At a glance this looks perfectly fine. I can even run the individual commands on the command line. The “if” statement runs fine, the “set” statement also runs ok. However, running them together like above results in this:

\Microsoft was unexpected at this time.

I scratched my head for quite a while. Looking for help in “if”, “cmd”, or searching online did not help either. Is this a Windows 7 incompatibility?

It was just by luck that I suddenly noticed the “(“ and “)”. Apparently the “set” statement contains “(“ and “)”, which likely confused the command host. More experiments reveal that even if only the variable value contains “(“ / “)”, this problem still happens. The command host expands the variables upon “if” statement being seen. As a result, the script below still won’t run:

Set ProgramFilesX86=%ProgramFiles(x86)%
if Exist "%ProgramFilesX86%\Microsoft Visual Studio 10.0" (
    Set VS10=%ProgramFilesX86%\Microsoft Visual Studio 10.0
)

To work around this issue, the final solution I come up with is to combine “delayed variable expansion”:

setlocal ENABLEDELAYEDEXPANSION

Set ProgramFilesX86=%ProgramFiles(x86)%
if Exist "%ProgramFilesX86%\Microsoft Visual Studio 10.0" (
    Set VS10=!ProgramFilesX86!\Microsoft Visual Studio 10.0
)

Technorati Tags: ,,

Sunday, December 06, 2009

PowerShell Splat Operator

There is a new “splat” operator in PowerShell v2 which is quite useful but not well documented. The best info I can find is from this blog. From a PowerShell console I can see help content of “about_Split” and “about_Join”, but not “about_Splat”, or anything mentioned in “about_Operators”.

It is described that this new splat operator “@” can be used to pass a collection as parameters to a function. It’s easy to find out the details by experiments. First, draft a test function:

PS> function Echo-Args
>>  {
>>      echo "=== Args: ($($args.Length)) ==="
>>      echo $args
>>  }
PS>
PS> Echo-Args a b c 1 2 3
=== Args: (6) ===
a
b
c
1
2
3

Try it out with an array:

PS> $a = @(1,2,3)
PS> Echo-Args $a
=== Args: (1) ===
1
2
3
PS> Echo-Args @a
=== Args: (3) ===
1
2
3

See the difference of passing “$a” and “@a”? “$a” passes the whole array as one parameter. “@a” passes the elements as parameters.

To admit it, I was testing this for several days, but every time I ran into an “invalid operator” kind of error, because I was using “@$a”.

Now try it out with a hash table:

PS> $a = @{a=1;b=2;c=3}
PS> Echo-Args @a
=== Args: (6) ===
c
3
b
2
a
1
PS> function f($A, $B, $C) { $PSBoundParameters }
PS> f @a

Key                                                                       Value
---                                                                       -----
C                                                                             3
B                                                                             2
A                                                                             1


PS> $a = @{"-a"=1;"-b"=2;"-c"=3}
PS> f @a

Key                                                                       Value
---                                                                       -----
A                                                                             1
C                                                                             3
B                                                                             2

Now this is interesting. So you can splat and pass a hash table of parameters to a function, and PowerShell will always try to “do it right”. When the function is expecting named parameters, PowerShell can match them with or without leading “-“.

In summary, this splat operator is quite useful when you just want to pass some collection of parameters to another function, e.g. the current “$args” or “$PSBoundParameters”, with or without modification.

Technorati Tags: ,

Saturday, November 28, 2009

WPF Command

image

In WPF Skinning, I was using old school MenuItem_Click event handling. WPF has a more powerful commanding system. To implement the same functionality with WPF command, first create a command in Window1:

public static readonly RoutedCommand ChangeSkin = new RoutedCommand(
    "ChangeSkin", typeof(Window1));

Bind the menu items to be sources of this command. Each binds to the same command with a different parameter. Now MenuItem_Click event handling can be removed and IsChecked binding can be one-way. I’ll use the command to change skin and only need menu items to display correct check marks.

<MenuItem Header="_Default"
        Command="local:Window1.ChangeSkin" CommandParameter="Default"
        IsChecked="{Binding Mode=OneWay, ElementName=mainWindow, Path=Skin,
              Converter={StaticResource skinEquals},
              ConverterParameter=Default}"/>
<MenuItem Header="_Green"
        Command="local:Window1.ChangeSkin" CommandParameter="Green"
        IsChecked="{Binding Mode=OneWay, ElementName=mainWindow, Path=Skin,
              Converter={StaticResource skinEquals},
              ConverterParameter=Green}"/>
<MenuItem Header="_Red"
        Command="local:Window1.ChangeSkin" CommandParameter="Red"
        IsChecked="{Binding Mode=OneWay, ElementName=mainWindow, Path=Skin,
              Converter={StaticResource skinEquals},
              ConverterParameter=Red}"/>

The command will bubble up until being handled. Create a command binding at the main window:

<Window.CommandBindings>
    <CommandBinding Command="local:Window1.ChangeSkin" Executed="ChangeSkin_Executed" />
</Window.CommandBindings>

Fill the command handling code:

private void ChangeSkin_Executed(object sender, ExecutedRoutedEventArgs e)
{
    Skin = (string)e.Parameter;
    e.Handled = true;
}

Now this should work the same as previous version.

The menu items do not have keyboard short-cuts (KeyGestures) yet. To make keyboard inputs invoke this command, add key bindings:

<Window.InputBindings>
    <KeyBinding Command="local:Window1.ChangeSkin" CommandParameter="Default"
               Key="D" Modifiers="Ctrl" />
    <KeyBinding Command="local:Window1.ChangeSkin" CommandParameter="Green"
               Key="G" Modifiers="Ctrl" />
    <KeyBinding Command="local:Window1.ChangeSkin" CommandParameter="Red"
               Key="R" Modifiers="Ctrl" />
</Window.InputBindings>

This makes the key gestures work, but they don’t show up in the menu items. They need to be specified in menu items, e.g.:

<MenuItem Header="_Green"
         Command="local:Window1.ChangeSkin" CommandParameter="Green"
         InputGestureText="Ctrl+G"
         IsChecked="{Binding Mode=OneWay, ElementName=mainWindow, Path=Skin,
           Converter={StaticResource skinEquals},
           ConverterParameter=Green}"/>

Alternatively, I can create 3 different commands and omit the above InputGestureText and even Header text:

public static readonly RoutedCommand DefaultSkin = new RoutedUICommand(
    "_Default", "Default", typeof(Window1),
    new InputGestureCollection(
        new KeyGesture[] { new KeyGesture(Key.D, ModifierKeys.Control) }));

public static readonly RoutedCommand GreenSkin = new RoutedUICommand(
    "_Green", "Green", typeof(Window1),
    new InputGestureCollection(
        new KeyGesture[] { new KeyGesture(Key.G, ModifierKeys.Control) }));

public static readonly RoutedCommand RedSkin = new RoutedUICommand(
    "_Red", "Red", typeof(Window1),
    new InputGestureCollection(
        new KeyGesture[] { new KeyGesture(Key.R, ModifierKeys.Control) }));

private void ChangeSkin_Executed(object sender, ExecutedRoutedEventArgs e)
{
    Skin = ((RoutedUICommand)e.Command).Name;
    e.Handled = true;
}

This time UI xaml is much cleaner:

<Window.CommandBindings>
    <CommandBinding Command="local:Window1.DefaultSkin" Executed="ChangeSkin_Executed" />
    <CommandBinding Command="local:Window1.GreenSkin" Executed="ChangeSkin_Executed" />
    <CommandBinding Command="local:Window1.RedSkin" Executed="ChangeSkin_Executed" />
</Window.CommandBindings>

<DockPanel x:Name="framePanel" LastChildFill="True">

    <Menu IsMainMenu="True" DockPanel.Dock="Top">
        <MenuItem Header="_Skins">
            <MenuItem Command="local:Window1.DefaultSkin"
                     IsChecked="{Binding Mode=OneWay, ElementName=mainWindow, Path=Skin,
                           Converter={StaticResource skinEquals}, ConverterParameter=Default}"/>
            <MenuItem Command="local:Window1.GreenSkin"
                     IsChecked="{Binding Mode=OneWay, ElementName=mainWindow, Path=Skin,
                           Converter={StaticResource skinEquals}, ConverterParameter=Green}"/>
            <MenuItem Command="local:Window1.RedSkin"
                     IsChecked="{Binding Mode=OneWay, ElementName=mainWindow, Path=Skin,
                           Converter={StaticResource skinEquals}, ConverterParameter=Red}"/>
        </MenuItem>
    </Menu>
   
    <Grid Background="{DynamicResource bgbrush}">
        <TextBlock
           Text="{Binding ElementName=mainWindow, Path=Skin}"
           HorizontalAlignment="Center"
           VerticalAlignment="Center"/>
    </Grid>
</DockPanel>

WPF Skinning

I was planning to learn about WPF skinning for this week. Here we go.

image image

Create 3 sets of “skin” – WPF resource dictionaries:

Default:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
   
    <LinearGradientBrush x:Key="bgbrush">
        <GradientStop Color="White" Offset="0" />
        <GradientStop Color="Blue" Offset="1" />
    </LinearGradientBrush>
   
</ResourceDictionary>

Green:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
   
    <LinearGradientBrush x:Key="bgbrush">
        <GradientStop Color="White" Offset="0" />
        <GradientStop Color="Green" Offset="1" />
    </LinearGradientBrush>
   
</ResourceDictionary>

Red:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
   
    <LinearGradientBrush x:Key="bgbrush">
        <GradientStop Color="Cyan" Offset="0" />
        <GradientStop Color="Red" Offset="1" />
    </LinearGradientBrush>
   
</ResourceDictionary>

In App.xaml, use the default skin:

<Application.Resources>
   
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="Skins\Default.xaml" />
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
    
</Application.Resources>

I want to use a menu to switch the skins, and put a check mark at the current skin. This sounds like a property binding. So create a dependency property on the main window class and perform the skin switching when property changed:

public static readonly DependencyProperty SkinProperty = DependencyProperty.Register(
    "Skin", typeof(string), typeof(Window1), new PropertyMetadata("Default", OnSkinChanged));

public string Skin
{
    get { return (string)GetValue(SkinProperty); }
    set { SetValue(SkinProperty, value); }
}

private static void OnSkinChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    string skin = e.NewValue as string;
    ResourceDictionary res = (ResourceDictionary)Application.LoadComponent(
        new Uri(string.Format(@"Skins\{0}.xaml", skin), UriKind.Relative));
    Application.Current.Resources = res;
}

I want a menu item to be checked if the current Skin matches the menu item. Looks like I need a value converter check Equals… I can’t find an existing one. On the other hand, when a menu item becomes checked, I want to update the Skin property. I end up creating a value converter:

public class SkinEqualsConverter : IValueConverter
{
    #region IValueConverter Members

    public object Convert(object value, Type targetType, object parameter,
        CultureInfo culture)
    {
        return object.Equals(value, parameter);
    }

    public object ConvertBack(object value, Type targetType, object parameter,
        CultureInfo culture)
    {
        return (bool)value ? parameter : DependencyProperty.UnsetValue;
    }

    #endregion
}

Now if a menu item is clicked, we only need to set its IsChecked to true and let data binding update the Skin. Setting MenuItem.IsCheckable to true almost satisfies my requirements. When clicked and IsChecked is turned on, everything works. However, I can’t prevent a user to click it again and uncheck the menu item. In that case Skin is not changed, but the check mark is gone. Finally I decide to handle the click manually:

private void SkinItem_Click(object sender, RoutedEventArgs e)
{
    MenuItem menu = (MenuItem)sender;
    menu.IsChecked = true;
}

The main window xaml is like the following. When a menu item is clicked, the above handler would turn on IsChecked, the binding will invoke the converter to get the parameter skin name, and bind that name to the above Skin property, causing the skin switch. Other menu items will uncheck because the binding invokes the converter and check if the current Skin equals to the converter parameter skin. In the UI I use DynamicResource to refer to skin resources so that UI refreshes dynamically when skin resources are replaced at runtime.

<Window x:Class="SkinApp.Window1"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:local="clr-namespace:SkinApp"
      x:Name="mainWindow"       
      Title="Window1" Height="300" Width="300">

    <Window.Resources>
        <local:SkinEqualsConverter x:Key="skinEquals" />
    </Window.Resources>

    <DockPanel x:Name="framePanel" LastChildFill="True">
        <Menu IsMainMenu="True" DockPanel.Dock="Top">
            <MenuItem Header="_Skins">
                <MenuItem Header="_Default" Click="SkinItem_Click"
                        IsChecked="{Binding ElementName=mainWindow, Path=Skin,
                              Converter={StaticResource skinEquals},
                              ConverterParameter=Default}"/>
                <MenuItem Header="_Green" Click="SkinItem_Click"
                        IsChecked="{Binding ElementName=mainWindow, Path=Skin,
                              Converter={StaticResource skinEquals},
                              ConverterParameter=Green}"/>
                <MenuItem Header="_Red" Click="SkinItem_Click"
                        IsChecked="{Binding ElementName=mainWindow, Path=Skin,
                              Converter={StaticResource skinEquals},
                              ConverterParameter=Red}"/>
            </MenuItem>
        </Menu>

        <Grid Background="{DynamicResource bgbrush}">
            <TextBlock
              Text="{Binding ElementName=mainWindow, Path=Skin}"
              HorizontalAlignment="Center"
              VerticalAlignment="Center"/>
        </Grid>
    </DockPanel>

</Window>

Friday, November 27, 2009

WPF Data Binding: Objects and XML Data

 image

ObjectDataProvider can be used to create new objects directly in xaml. However, typically objects are created in code and in such cases the binding needs to be set in code. Assuming we have these objects:

class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int Age { get; set; }

    public static Person[] Friends = new Person[] {
        new Person() { FirstName="Michael", LastName="Xu", Age=9 },
        new Person() { FirstName="Michael", LastName="Xu", Age=9 },
        new Person() { FirstName="Michael", LastName="Xu", Age=9 },
        new Person() { FirstName="Michael", LastName="Xu", Age=9 },
        new Person() { FirstName="Michael", LastName="Xu", Age=9 },
    };
}

To bind these to a ListView, create a ListView style with a data template:

<Window.Resources>

    <Style x:Key="personList" TargetType="{x:Type ListView}">
        <Setter Property="ItemTemplate">
            <Setter.Value>
                <DataTemplate>
                    <StackPanel>
                        <StackPanel Orientation="Horizontal">
                            <TextBlock Text="{Binding Path=FirstName}"
                                       FontWeight="Bold" />
                            <TextBlock Text="{Binding Path=LastName}"
                                       FontWeight="Bold" Margin="8,0,0,0" />
                        </StackPanel>
                        <TextBlock Text="{Binding Path=Age}" />
                    </StackPanel>
                </DataTemplate>
            </Setter.Value>
        </Setter>
    </Style>

Create a ListView control with the style:

<ListView
    Name="friendsListView"
    Style="{StaticResource personList}" />

Then create the binding in code:

private void Window_Loaded(object sender, RoutedEventArgs e)
{
    friendsListView.ItemsSource = Person.Friends;
}

To achieve similar results with an embeded XmlDataProvider, we can directly supply data and use XPath binding (note the xmlns).

<XmlDataProvider x:Key="xmlFriends">
    <x:XData>
        <Friends xmlns="">
            <Person FirstName="Michael" LastName="Xu" Age="10" />
            <Person FirstName="Michael" LastName="Xu" Age="10" />
            <Person FirstName="Michael" LastName="Xu" Age="10" />
            <Person FirstName="Michael" LastName="Xu" Age="10" />
            <Person FirstName="Michael" LastName="Xu" Age="10" />
            <Person FirstName="Michael" LastName="Xu" Age="10" />
            <Person FirstName="Michael" LastName="Xu" Age="10" />
            <Person FirstName="Michael" LastName="Xu" Age="10" />
        </Friends>
    </x:XData>
</XmlDataProvider>

<Style x:Key="xmlPersonList" TargetType="{x:Type ListView}">
    <Setter Property="ItemTemplate">
        <Setter.Value>
            <DataTemplate>
                <StackPanel>
                    <StackPanel Orientation="Horizontal">
                        <TextBlock Text="{Binding XPath=@FirstName}"
                                   FontWeight="Bold" />
                        <TextBlock Text="{Binding XPath=@LastName}"
                                   FontWeight="Bold" Margin="8,0,0,0" />
                    </StackPanel>
                    <TextBlock Text="{Binding XPath=@Age}" />
                </StackPanel>
            </DataTemplate>
        </Setter.Value>
    </Setter>
</Style>

Bind to a ListView:

<ListView 
    Style="{StaticResource xmlPersonList}"
    ItemsSource="{Binding Source={StaticResource xmlFriends}, XPath=/Friends/Person}" />

Monday, January 08, 2007

Update Windows desktop icons

When Windows desktop icons seem out of sync, try changing display depth (display settings/colors). This will rebuild Windows icon cache.

Saturday, December 30, 2006

Convert Between Polygon Shape File and Arc/Info Coverage

Sometimes you want to take advantage of the old Arc/Info command lines... e.g., you want to run CLEAN, or you have many files to process and you want to run a simple script.

However, when converting between a shape file and arc/info coverage, you usually lose attribute data. To preserve attribute data, follow this example:

# import as region
shapearc oxbld.shp oxr REGION

# clean poly
clean oxr oxrc # # POLY

# export region
arcshape oxrc REGIONS.REGION oxr

Friday, December 01, 2006

javascript in href

There are two ways to use javascript in a href tag, e. g.,

1. <a href="javascript:doSomething()">...</a>
2. <a href="#" onclick="doSomething(); return false">...</a>


When using Microsoft HTA, however, only the second approach works. The first one will pop up a new window when the link is clicked, even under IE7.