У меня есть окна Windows Forms с элементом управления вкладками и один из его вкладчиков ElementHost с ContentControl как дочерний элемент. Этот элемент управления имеет набор привязок ввода, которые работают только тогда, когда у любого дочернего элемента есть фокус ввода, но если фокус потерян, он больше не реагирует. Можно ли определить такие привязки ввода на более высоком уровне в такой ситуации?Как использовать привязки ввода для команд при размещении содержимого WPF в WinForms
ответ
Одним из решений может быть передача (туннель) клавиатуры и/или событий мыши из Win Forms на хост WPF. Я сделал следующее доказательство концепции. Он работает, но имеет ограничения и требует больше работы. Сначала вам понадобится класс, полученный от ElementHost. Вы должны использовать его в своем приложении вместо стандартного ElementHost. Этот новый пользовательский класс будет иметь только один дополнительный метод: ProcessWinFormsKeys, который будет сопоставлять определенные ключи WinForms тем, которые используются WPF. Затем он найдет правильную привязку ввода и выполнит ее.
public class CustomElementHost : ElementHost
{
public void ProcessWinFormsKeys(Keys keys, Keys modifiers)
{
var key = KeyInterop.KeyFromVirtualKey((int)keys);
var modifier = System.Windows.Input.ModifierKeys.None;
if ((modifiers & Keys.Control) != 0)
modifier |= System.Windows.Input.ModifierKeys.Control;
if ((modifiers & Keys.Shift) != 0)
modifier |= System.Windows.Input.ModifierKeys.Shift;
if ((modifiers & Keys.Alt) != 0)
modifier |= System.Windows.Input.ModifierKeys.Alt;
foreach (InputBinding inputBinding in Child.InputBindings)
{
var keyGesture = inputBinding.Gesture as KeyGesture;
if (keyGesture == null)
continue;
if(keyGesture.Key == key && keyGesture.Modifiers == modifier)
if(inputBinding.Command.CanExecute(inputBinding.CommandParameter))
inputBinding.Command.Execute(inputBinding.CommandParameter);
}
}
}
Затем в формы, который содержит экземпляр CustomElementHost вы должны подписаться KeyDown события и вызвать ProcessWinFormsKeys метода внутри обработчика:
public Form()
{
InitializeComponent();
KeyPreview = true;
KeyDown += Form_KeyDown;
...
}
void Form_KeyDown(object sender, KeyEventArgs e)
{
elementHost.ProcessWinFormsKeys(e.KeyCode, e.Modifiers);
}
Другим решением может быть используйте глобальные горячие клавиши. Это потребует использования функции RegisterHotKey от user32.dll. Тем не менее, я не уверен, будет ли он работать с ElementHost. Если вы хотите попробовать, есть несколько вопросов о stackoverflow и десятках статей в Интернете.
Не могли бы вы опубликовать код, чтобы сделать его более конкретным? Как выглядят ваши привязки и каково ваше предложение по размещению их на более высоком уровне (я думаю, это не будет хорошим решением) –
Связывание довольно простое, что-то вроде –
Demarsch
И если окна образуют контент, как-то получить фокус, эти привязки клавиш больше не могут быть активированы. В WPF вы можете поместить свои привязки в элемент Window, и все будет работать. – Demarsch