0

与えられた:

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>

    <Grid.CommandBindings>
        <CommandBinding Command="Cut" 
                        Executed="CommandBinding_Executed"/>
    </Grid.CommandBindings>

    <TextBox x:Name="WpfTextBox" 
             VerticalAlignment="Center" 
             Text="Hello there" />

    <WindowsFormsHost Grid.Column="1" 
                      VerticalAlignment="Center">
        <wf:TextBox x:Name="WinFormsTextBox" 
                    Text="Hello there" />
    </WindowsFormsHost>
</Grid>

Ctrl+Xを押すと発火しWinFormsTextBoxますCommandBinding_Executedが、 にいるときは発火しませんWpfTextBox

WpfTextBoxforの振る舞いをしたいですWinFormsTextBox。つまり、コマンドは、何もフォーカスがない場合にのみ起動する必要があります。これは、グローバル ビュー コマンドなどのように機能する必要があります。

注: コマンドのイベントにハンドラーを追加することは、 ( +が-に設定されている場合、テキストがカットされないことを意味する)CanExecuteで何かが発生するのを防ぐか、通常どおり実行するのに役立つだけです。WinFormsTextBoxCtrlXe.CanExecutetrue

注 2: カットは単なる例です。任意のコマンド バインディングで機能するソリューションが必要です。

注 3: ListView などのように、フォーカスがある場合、コマンドは別のコントロールから起動できる必要があります。内部にフォーカスのある TextBox がない限り (編集モードを考えてください)。

メソッドに特定の処理を追加する必要があることを受け入れたくありませんCommandBinding_Executed。でも、C'est la vie。

4

2 に答える 2

0

少しばかげた問題に対する少しばかげた解決策。これは私の最終的な解決策の単純なバージョンです:

private void CommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
    e.ContinueRouting = IsFocusInWinFormsInputControl();
}

private static bool IsFocusInWinFormsInputControl()
{
    // Try get focus control
    WinForms.Control focusedWinFormsControl = GetFocusedWinFormsControl();

    // Is there anything and is it a textbox etc?
    return focusedWinFormsControl != null &&
        (focusedWinFormsControl is WinForms.TextBox ||
         focusedWinFormsControl is WinForms.RichTextBox);
}

private static WinForms.Control GetFocusedWinFormsControl()
{
    // Try get focused WinForms control
    IntPtr focusedControlHandle = GetFocus();

    WinForms.Control focusedControl = null;
    if (focusedControlHandle != IntPtr.Zero)
    {
        // Note: If focused Control is not a WinForms control, this will return null
        focusedControl = WinForms.Control.FromHandle(focusedControlHandle);
    }

    return focusedControl;
}

[DllImport("user32.dll")]
private static extern IntPtr GetFocus();

基本的に、コマンド検証ロジックを追加して、WinForms TextBox の外にいる場合にのみコマンドを実行します。

于 2011-09-26T09:29:09.527 に答える
0

WPF コマンドがルーティングされ、WindowsFormsHost の親コントロールで Ctrl+X コマンドの CommandBinding を定義しました。したがって、WPF TextBox でのみ処理する場合は、Grid から CommandBinding を削除してそこに配置します。

<TextBox>    
    <TextBox.CommandBindings>
        <CommandBinding Command="Cut" 
                        Executed="CommandBinding_Executed"/>
    </TextBox.CommandBindings>
</TextBox>

コマンドがルーティングされると、Ctrl+X コマンドは、このコマンドのバインドを持つ最初の親によって処理されます。フォーカスがグリッドのスコープ内にあり、Ctrl+X コマンドを実行している限り、グリッド コマンド バインディングがそれを処理します。


WPF のルーティング イベントとコマンドに関する優れた記事は次のとおりです。 WPF のルーティング イベントとコマンドについて


編集:

TextBox 内でコマンドを処理したくない場合は、Ctrl+X が適切な場所でのみ CommandBindings を定義する必要があります。別の解決策はないと思います。いずれにせよ、通常、Cut のような ApplicationCommands は、RichTextBox や ListBox などの特定のスコープに対してコンテキストに依存します。


編集:

WindowsFormsHost が基になるルーティング コマンドを起動するのをブロックすることはできません。ただし、できることは、ホストを CommandBindings スコープから削除することだけです。

<Grid>
    <Grid.ColumnDefinitions>
       <ColumnDefinition Width="*" />
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>

    <Grid Grid.Column="0">
        <Grid.CommandBindings>
            <CommandBinding Command="Cut" 
                            Executed="CommandBinding_Executed"/>
        </Grid.CommandBindings>

        <TextBox x:Name="WpfTextBox" 
                VerticalAlignment="Center" 
                Text="Hello there" />
    </Grid>

    <WindowsFormsHost Grid.Column="1" 
                      VerticalAlignment="Center">
        <wf:TextBox x:Name="WinFormsTextBox" 
                    Text="Hello there" />
    </WindowsFormsHost>
</Grid>

もちろん、レイアウトするオブジェクトがはるかに多い場合は、少し難しいかもしれませんが、うまくいきます。コマンドを処理したくないオブジェクトを CommandBindings のスコープから削除するだけです。

于 2011-09-22T11:13:49.367 に答える