#1,118 – An Example of Input that Obeys CurrentCulture

One step in internationalizing an application is to respect the current regional settings when reading numeric or date/time values from a user.

If you are parsing user-entered text and converting to numeric or date/time data, the Parse methods associated with individual data types respect the current regional settings.

Below, we read text from two TextBox controls, interpreting the first value as a double and the second as a DateTime using the corresponding Parse method.

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                double num = double.Parse(txt1.Text);
                DateTime dt = DateTime.Parse(txt2.Text);
            }
            catch (Exception xx)
            {
                MessageBox.Show(xx.ToString());
            }
        }

On an English/US system, we can enter the data as “1.1” and “5/2/12”.  The date is interpreted as May 2nd.

1118-001

For French/France, we must enter “1,1” for the double.  “5/2/12” is interpreted as Feb 5th.

1118-002

#1,117 – Internationalization II – Obey CurrentCulture for Input

The first step in internationalizing an application is to ensure that your application honors the user’s current regional settings, as reflected by the CurrentCulture property of the application’s main thread.

Current culture impacts not only how you display the following types of data, but also how the user inputs this data:

  • Numeric data
  • Date/time values

These values are typically stored internally as numeric (e.g. double, int) or DateTime values.  The values exist in memory in a culture-agnostic form.  You need to worry about regional settings only when you display a value to the user or receive input from the user.

In .NET, if you use the Parse method of a numeric or date/time type to convert a user-supplied string to the internal type, the parse operation will expect the string to be in a format that is valid for the current region.

 

#1,084 – A KeyBinding Binds a Command to a Key

A user interface element has a CommandBindings collection containing command binding objects that indicate which commands are supported for the element and the code that the command is bound to.

User interface elements also have an InputBindings collection that contains KeyBinding and MouseBinding instances, each of which maps keyboard or mouse input to a command that is also present in the CommandBindings collection.

In the code below, we wire up the Open command for both key (Ctrl+O) and mouse (Ctrl+Left Click) input.

        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = this;

            this.CommandBindings.Add(new CommandBinding(ApplicationCommands.Open,
               (sender, e) => { MessageBox.Show("Executing the Open command"); },
               (sender, e) => { e.CanExecute = CanOpenIsChecked; }));

            // Ctrl+O = Open
            this.InputBindings.Add(new KeyBinding(ApplicationCommands.Open,
                new KeyGesture(Key.O, ModifierKeys.Control)));

            // Ctrl+Left Mouse Click = Open
            this.InputBindings.Add(new MouseBinding(ApplicationCommands.Open,
                new MouseGesture(MouseAction.LeftClick, ModifierKeys.Control)));
        }

We can now use either form of input to execute the Open command.

1084-001

#1,077 – Checking for Single Modifer vs. Multiple Modifier Keys

In keypress events, you can check to see if the user is also holding down one of the modifier keys (Ctrl, Alt, Shift, or Windows key).  You do this by checking the KeyEventArgs.KeyboardDevice.Modifiers property.

You sometimes want to check to see if one and only one modifier key is being held down (e.g. Ctrl key without Alt, Shift, or Windows).  You do this by checking to see if the Modifiers property is equal to one of the ModifierKeys enumerated values.

            if ((e.Key == Key.G) &&
                (e.KeyboardDevice.Modifiers == ModifierKeys.Control))
                MessageBox.Show("Ctrl+G detected, NO Alt/Shift/Windows");

You may also want to check to see if the control key is being pressed, either alone or in conjunction with one of the other modifier keys.  You do this by using a mask.

            if ((e.Key == Key.G) &&
                ((e.KeyboardDevice.Modifiers & ModifierKeys.Control) == ModifierKeys.Control))
                MessageBox.Show("Ctrl+G or Ctrl+Alt+G, Ctrl+Alt+Windows+G, etc.");

#1,076 – Two Ways to Check for Use of Modifier Keys in Keypress Handlers

You can check for the presence of modifier keys (e.g. Alt, Ctrl, Shift, or Windows key) in keypress handlers using the KeyboardDevice.Modifier property.  For example:

        private void Window_KeyDown(object sender, KeyEventArgs e)
        {
            if ((e.Key == Key.G) &&
                (e.KeyboardDevice.Modifiers == ModifierKeys.Control))
                MessageBox.Show("Ctrl+G detected");
        }

Note that this method doesn’t distinguish between whether you pressed the left vs. right Ctrl keys.  This is normally what you want.  If you do want to distinguish between the two, you can explicitly check for left vs. right.

        private void Window_KeyDown(object sender, KeyEventArgs e)
        {
            if ((e.Key == Key.G) &&
                (Keyboard.IsKeyDown(Key.LeftCtrl)))
                MessageBox.Show("Left Ctrl+G detected");
            else if ((e.Key == Key.G) &&
                (Keyboard.IsKeyDown(Key.RightCtrl)))
                MessageBox.Show("Right Ctrl+G detected");
        }

#1,075 – Triggering on IsKeyboardFocusWithin Property

You can set up a trigger that fires whenever a control’s IsKeyboardFocused property becomes truechanging the value of some other property when the control gains keyboard focus.

You can also trigger on the IsKeyboardFocusWithin property.  This property will get set to true for an element when any child of that element has keyboard focus.

In the example below, we set the background color of either StackPanel when any element within the StackPanel has focus.  This technique may be useful when you want to keep track of what section of a window the user is working in and do something based on that knowledge.

    <Window.Resources>
        <Style x:Key="HoneydewFocus" TargetType="StackPanel">
            <Style.Triggers>
                <Trigger Property="IsKeyboardFocusWithin" Value="true">
                    <Setter Property="Background" Value="Honeydew"/>
                </Trigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>
    
    <StackPanel>
        <StackPanel Orientation="Horizontal" Margin="10"
                    Style="{StaticResource HoneydewFocus}">
            <Button Content="Click Me" VerticalAlignment="Center"/>
            <TextBox Width="200" Height="25" Margin="10"/>
        </StackPanel>

        <StackPanel Orientation="Horizontal" Margin="10"
                    Style="{StaticResource HoneydewFocus}">
            <Button Content="Or Me" VerticalAlignment="Center"/>
            <TextBox Width="200" Height="25" Margin="10"/>
        </StackPanel>
    </StackPanel>

1075-001

1075-002

#1,072 – Adding Custom Triggers Related to Keyboard Focus

The default control template for the TextBox control changes the color of the Border around the control when the control gets focus.  It does this by using a trigger hooked to the IsKeyboardFocused property.

You can add your own triggers related to keyboard focus by defining a custom property trigger.  The XAML fragment below defines a new Style element that changes the Background of the control when IsKeyboardFocused is true.

    <Window.Resources>
        <Style x:Key="HoneydewFocus" TargetType="TextBox">
            <Style.Triggers>
                <Trigger Property="IsKeyboardFocused" Value="true">
                    <Setter Property="Background" Value="Honeydew"/>
                </Trigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>

    <StackPanel>
        <TextBox Margin="5" Width="80"
                 Style="{StaticResource HoneydewFocus}"/>

        <TextBox Margin="5" Width="80"
                 Style="{StaticResource HoneydewFocus}"/>

        <Button Content="Click Me" HorizontalAlignment="Center"
                Padding="12,5" Margin="5" />
    </StackPanel>

As we tab between the two TextBox controls, the one with keyboard focus will have a Honeydew-colored background, as well as the default blue border.

1072-001