2011-09-22 57 views
0

鉴于其焦点:WPF命令触发,尽管在文本框的WinForms

<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 +XWinFormsTextBox原因CommandBinding_Executed火,但是当你不在WpfTextBox

我希望WpfTextBoxWinFormsTextBox的行为。即该命令只能在没有焦点时触发 - 它应该像全局视图命令或其他东西一样工作。

注:添加一个处理程序命令的CanExecute事件仅艾滋病,或是防止任何从发生的WinFormsTextBox按Ctrl + Xe.CanExecute设置为true完全吞噬 - 这意味着没有文字显示) ,或者正常运行。注意2:Cut只是一个例子,我想要一个可以用于任何命令绑定的解决方案。注意3:命令应该能够从另一个控件触发,如果它有焦点 - 就像一个ListView或其他东西。除非它有一个TextBox,它有焦点(认为编辑模式)。

我不确定任何事情都可以完成,我不想接受在CommandBinding_Executed方法中添加特定的处理。但是,C'est la vie。

回答

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文本框之外,添加命令验证逻辑以仅执行命令。

0

WPF命令将被路由,并且您在WindowsFormsHost的父控件中为Ctrl + X命令定义了CommandBinding。所以,如果你想让它仅仅在WPF文本框从网格中删除您的CommandBinding并把它放在那里进行处理:

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

当命令被路由,按Ctrl + X命令将被由具有第一父处理绑定这个命令。只要你的焦点在Grid的范围内,并且你执行了Ctrl + X命令,Grid命令绑定就可以处理它。


这里是WPF约路由事件和命令的优秀文章:Understanding Routed Events and Commands In 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的作用域中删除不想处理命令的对象即可。

+0

我不希望在任一TextBox上发生该命令。它应该发生在任何TextBox之外。对不起,我看到这个例子有点误导,我会尝试编辑它。 – Locdarb

+0

我的实际最终目标是让代码中逻辑定义的命令具有上下文,但是会有一种装饰器UI来显示或说出命令将执行什么以及执行什么操作。对不起,这个答复的通用性,但我希望这可以帮助你看到我想要做什么! 我想我可能不得不放弃使用CommanBindings或WinForms。 – Locdarb

+0

那么,据我所知,你想在特定的UI范围内激活一个命令,但不希望它在该范围内的特定控件上处理。如果这是你真正想要的,那么它有点复杂。可以肯定的是,当您想要在UI范围内全局启用命令时,CommandBindings是一种方法。而且这个问题与WinForms无关。我建议你仔细看看WPF指令系统来理解这里的问题以及为什么这种行为是正常的。 – Ucodia