0
votes

A project i'm working on requires a shortcut key to access a save dialog to dump the contents of a rich text box element into a file.

My keybinding and command binding are being done in XAML but the code behind is what i think is messing up.

My key and command binding is set up like so.

<KeyBinding Command="local:customCommands.saveFile" Key="S" Modifiers="Ctrl"/>
...
<CommandBinding Command="local:customCommands.saveFile" Executed="launchSaveDialog"/>

And this is the code behind for the WPF window

private void launchSaveDialog(object sender, ExecutedRoutedEventArgs e)
    {
        SaveFileDialog dlg = new SaveFileDialog();
        dlg.Filter = "Rich Text format(*.rtf)|*.rtf|";
        dlg.DefaultExt = ".rtf";
        dlg.OverwritePrompt = true;
        if (dlg.ShowDialog() == true)
        {
            FileStream fileStream = new FileStream(dlg.FileName, FileMode.Create);
            TextRange range = new TextRange(RTB.Document.ContentStart, RTB.Document.ContentEnd);
            range.Save(fileStream, DataFormats.Rtf);
        }
    }

The save dialog doesn't show even though Ctrl+S is pressed. If it helps, the program runs full screen.

Also, is there a way of running a Winforms save dialog inside of the WPF app as a separate window

1
Where are the KeyBinding and CommandBinding defined in the XAML? You can find out if it's calling launchSaveDialog by putting a breakpoint in launchSaveDialog.15ee8f99-57ff-4f92-890c-b56153
You're definitely not calling launchSaveDialog, or you'd be seeing an exception about the invalid filter string. You need to remove the trailing pipe (|) character.15ee8f99-57ff-4f92-890c-b56153

1 Answers

0
votes

This worked on the first try for me (at least up until SaveFileDialog threw an exception about the filter string). I put the KeyBinding in Window.InputBindings and the CommandBinding in Window.CommandBindings.

<Window 
    x:Class="Test3.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:Test3"
    xmlns:commands="clr-namespace:Commands"
    Title="MainWindow" 
    Height="350" 
    Width="525">
    <Window.InputBindings>
        <KeyBinding Command="local:customCommands.saveFile" Key="S" Modifiers="Ctrl"/>
    </Window.InputBindings>
    <Window.CommandBindings>
        <CommandBinding Command="local:customCommands.saveFile" Executed="launchSaveDialog"/>
    </Window.CommandBindings>
    <Grid>
        <RichTextBox x:Name="RTB" />
    </Grid>
</Window>

I defined customCommands as follows:

public static class customCommands
{
    static customCommands()
    {
        saveFile = new RoutedCommand("saveFile", typeof(MainWindow));
    }
    public static RoutedCommand saveFile { get; private set; }
}

I got an exception about the filter string, due to the trailing pipe character. It seems to regard that as a separator, not a terminator:

Provided filter string is not valid. Filter string should contain a description of the filter, followed by a vertical bar and the filter pattern. Must also separate multiple filter description and pattern pairs by a vertical bar. Must separate multiple extensions in a filter pattern with a semicolon. Example: "Image files (*.bmp, .jpg)|.bmp;.jpg|All files (.)|.*"

Easy fix:

private void launchSaveDialog(object sender, ExecutedRoutedEventArgs e)
{
    SaveFileDialog dlg = new SaveFileDialog();
    dlg.Filter = "Rich Text format (*.rtf)|*.rtf";
    dlg.DefaultExt = ".rtf";
    dlg.OverwritePrompt = true;
    if (dlg.ShowDialog() == true)
    {
        FileStream fileStream = new FileStream(dlg.FileName, FileMode.Create);
        TextRange range = new TextRange(RTB.Document.ContentStart, RTB.Document.ContentEnd);
        range.Save(fileStream, DataFormats.Rtf);
    }
}

It's possible that you're eating keyboard input somewhere, but you didn't show that code so I'm just throwing it out there.

The insistence on javaCase names is relatively harmless but it does little for readability.