0
votes

I've got a requirement, where the same keyboard shortcuts have to behave the same way to set text properties in a WPF rich textbox independently of the language windows was installed in.

Shortcuts:

  • CTRL+B: Make text bold
  • CTRL+I: Make text italic
  • CTRL+SHIFT+S: Strike-trough text

enter image description here

Even though this shouldn't matter, as it has to behave the same way for all OS languages, the used locals are: EN-US, DE-DE, DE-CH, FR-FR, FR-CH, IT-IT, IT-CH

To implement this functionality, following code has been added as early as possible in the constructor of App.xaml.cs:

public App() {
   Thread.CurrentThread.Name = "Main";

   m_log.Info("Starting application");

   // Assign command bindings to be OS language independent
   EditingCommands.ToggleBold.InputGestures.Clear();
   EditingCommands.ToggleBold.InputGestures.Add(new KeyGesture(Key.B, ModifierKeys.Control));

   EditingCommands.ToggleItalic.InputGestures.Clear();
   EditingCommands.ToggleItalic.InputGestures.Add(new KeyGesture(Key.I, ModifierKeys.Control));

   TextFormattingCommands.ToggleStrikethrough.InputGestures.Clear();
   TextFormattingCommands.ToggleStrikethrough.InputGestures.Add(new KeyGesture(Key.S, ModifierKeys.Control | ModifierKeys.Shift));

   InitializeComponent();
}

Some observations:

  • For my EN-US system, both CTRL+B and CTRL+I worked without the above code, as these are the default shortcuts.
  • With the above code, CTRL+SHIFT+S made strike-through (which doesn't exist out of the box) work as expected.
  • When testing on a DE-DE system, CTRL+I and CTRL+SHIFT+S work, but CTRL+B doesn't.
  • Clearing the input gestures before setting them isn't really required, as InputGestures are empty for all of the above commands at this point.
  • Tests have been perfromed on Win7 x64, but should work independently of the used Windows version

Question: How can I guarantee that these editing shortcuts behave the same way independently of the installed OS language?

[edit] Here's the relevant part of the DataTemplate using the CommandBindings:

<DataTemplate x:Key="QualificationTextItemTemplate" DataType="DienstleistenderQualifikationMerkmaleEntity">
    <GroupBox>
        <Grid HorizontalAlignment="Stretch">
            <Grid.ColumnDefinitions>
                <ColumnDefinition SharedSizeGroup="MerkmaleColumn" MinWidth="480"
                                              Width="{Binding Path=ActualWidth, ConverterParameter=0.4,
                                                              RelativeSource={RelativeSource AncestorType=ListView, Mode=FindAncestor},
                                                              Converter={x:Static qualifikationen:QualificationItemFreeRichTextBoxWidthConverter.Instance}}"/>
                <ColumnDefinition SharedSizeGroup="OhneBeurteilungColumn" MinWidth="128"
                                              Width="{Binding Path=ActualWidth, ConverterParameter=0.1,
                                                              RelativeSource={RelativeSource AncestorType=ListView, Mode=FindAncestor},
                                                              Converter={x:Static qualifikationen:QualificationItemFreeRichTextBoxWidthConverter.Instance}}"/>
                <ColumnDefinition SharedSizeGroup="BeurteilungColumn" MinWidth="128"
                                              Width="{Binding Path=ActualWidth, ConverterParameter=0.1,
                                                              RelativeSource={RelativeSource AncestorType=ListView, Mode=FindAncestor},
                                                              Converter={x:Static qualifikationen:QualificationItemFreeRichTextBoxWidthConverter.Instance}}"/>
                <ColumnDefinition SharedSizeGroup="BemerkungColumn"
                                              Width="{Binding Path=ActualWidth, ConverterParameter=0.4,
                                                              RelativeSource={RelativeSource AncestorType=ListView, Mode=FindAncestor},
                                                              Converter={x:Static qualifikationen:QualificationItemFreeRichTextBoxWidthConverter.Instance}}"/>
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition />
                <RowDefinition />
            </Grid.RowDefinitions>
            [...]
            <UIControls:BindableRichTextBox Grid.Row="1" 
                                                        Grid.Column="0" 
                                                        Height="Auto" 
                                                        VerticalAlignment="Stretch" 
                                                        Margin="15 0 10 0"
                                                        SpellCheck.IsEnabled="False" 
                                                        MaxLength="2000"
                                                        DisplayedTextToBoundTextConverter="{x:Static qualifikationen:QualificationItemDescriptionValueConverter.XamlToMILOFormatConverter}"                                                        
                                                        BoundTextToDisplayedTextConverter="{x:Static qualifikationen:QualificationItemDescriptionValueConverter.MILOFormatToXamlConverter}"
                                                        Text="{Binding Path=Verhaltensmerkmal, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                                                        TextChangedManually="OnQualificationItemPropertyChanged" VerticalScrollBarVisibility="Auto">
                <RichTextBox.Resources>
                    <Style TargetType="{x:Type Paragraph}">
                        <Setter Property="Margin" Value="0"/>
                    </Style>
                </RichTextBox.Resources>
                <Control.Visibility>
                    <MultiBinding Converter="{x:Static qualifikationen:QualificationItemDescriptionVisibilityConverter.Instance}">
                        <Binding Path="QualifikationItem.ItemStyle" Mode="OneTime" />
                        <Binding Path="QualifikationItem.Protected" Mode="OneTime" />
                        <Binding Path="QualifikationItem.Description" Mode="OneTime" />
                    </MultiBinding>
                </Control.Visibility>
                <TextBoxBase.IsReadOnly>
                    <MultiBinding Converter="{x:Static qualifikationen:QualificationItemDescriptionReadOnlyConverter.Instance}">
                        <Binding Path="Visibility" RelativeSource="{RelativeSource Mode=Self}" />
                        <Binding Path="QualifikationItem.Protected" Mode="OneWay" />
                        <Binding Path="Beurteilt" />
                    </MultiBinding>
                </TextBoxBase.IsReadOnly>
                <RichTextBox.InputBindings>
                    <KeyBinding Command="ApplicationCommands.NotACommand" Key="U" Modifiers="Control"/>
                    <KeyBinding Command="ApplicationCommands.NotACommand" Key="L" Modifiers="Control"/>
                    <KeyBinding Command="ApplicationCommands.NotACommand" Key="E" Modifiers="Control"/>
                    <KeyBinding Command="ApplicationCommands.NotACommand" Key="R" Modifiers="Control"/>
                    <KeyBinding Command="ApplicationCommands.NotACommand" Key="OemCloseBrackets" Modifiers="Control"/>
                    <KeyBinding Command="ApplicationCommands.NotACommand" Key="OemOpenBrackets" Modifiers="Control"/>
                </RichTextBox.InputBindings>
                <RichTextBox.CommandBindings>
                    <CommandBinding Command="EditingCommands.ToggleBold"
                                                CanExecute="OnRichTextBoxEditingCommandsCanExecuteChecked" 
                                                Executed="OnRichTextBoxToggleBoldCommandExecuted"/>
                    <CommandBinding Command="EditingCommands.ToggleItalic"
                                                CanExecute="OnRichTextBoxEditingCommandsCanExecuteChecked" 
                                                Executed="OnRichTextBoxToggleItalicCommandExecuted"/>
                    <CommandBinding Command="FormattingCommands:TextFormattingCommands.ToggleStrikethrough"
                                                CanExecute="OnRichTextBoxEditingCommandsCanExecuteChecked" 
                                                Executed="OnRichTextBoxToggleStrikethroughCommandExecuted"/>
                </RichTextBox.CommandBindings>
                <Control.ContextMenu>
                    <ContextMenu>
                        <MenuItem Header="{rootLoc:LocText Dict=Resources, Key=ContextMenuCutHeader}" Command="ApplicationCommands.Cut"/>
                        <MenuItem Header="{rootLoc:LocText Dict=Resources, Key=ContextMenuCopyHeader}" Command="ApplicationCommands.Copy"/>
                        <MenuItem Header="{rootLoc:LocText Dict=Resources, Key=ContextMenuPasteHeader}" Command="ApplicationCommands.Paste"/>
                        <Separator />
                        <MenuItem Header="{LocText CommonResources:BoldButtonText}"
                                              Command="EditingCommands.ToggleBold" 
                                              InputGestureText="Ctrl+B"/>
                        <MenuItem Header="{LocText CommonResources:ItalicButtonText}"
                                              Command="EditingCommands.ToggleItalic" 
                                              InputGestureText="Ctrl+I"/>
                        <MenuItem Header="{LocText CommonResources:StrokeButtonText}"
                                              Command="FormattingCommands:TextFormattingCommands.ToggleStrikethrough"
                                              InputGestureText="Ctrl+Shift+S"/>
                    </ContextMenu>
                </Control.ContextMenu>
            </UIControls:BindableRichTextBox>
            [...]
        </Grid>
    </GroupBox>
</DataTemplate>

[edit2] On the DE-DE machine (where CTRL+B isn't working), the same shortcut is working in Wordpad. Not sure if Wordpad overrides the default shortcut as I couldn't find any hint on the shortcut to use. At least in Word, the shortcut is CTRL+SHIFT+F (http://forum.chip.de/office/tastaturkuerzel-fuer-fett-unterstrichen-kursiv-548164.html)

[edit3] When changing the the input gesture to CTRL+Q (just to test another key combination) using EditingCommands.ToggleBold.InputGestures.Add(new KeyGesture(Key.Q, ModifierKeys.Control));, CTRL+Q makes the text bold for all OS languages.

1

1 Answers

1
votes

Hi I have the same Problem with German OS, and the shortcut too

You have to change the Culture Property of your App try this in your MainWindow Constructor

CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("en-US"); CultureInfo.DefaultThreadCurrentUICulture = new CultureInfo("en-US");

for other OS, I guest you just have to change the CultureInfo