Rõ ràng, có một số vấn đề về bàn phím và tập trung nghiêm trọng với WPF WebBrowser control. Tôi đã đặt cùng một ứng dụng WPF tầm thường, chỉ cần một WebBrowser và hai nút. Ứng dụng tải một đánh dấu HTML có thể chỉnh sửa rất cơ bản (<body contentEditable='true'>some text</body>
) và thể hiện các điều sau:Bàn phím điều khiển WebBrowser và hành vi lấy nét
Tab đang hoạt động không đúng. Người dùng cần nhấn Tab hai lần để xem dấu mũ (con trỏ văn bản) bên trong WebBrowser và có thể nhập.
Khi người dùng chuyển từ ứng dụng (ví dụ: bằng Alt-Tab), sau đó quay lại, dấu mũ đã biến mất và cô ấy không thể nhập gì cả. Một cú click chuột vật lý vào khu vực cửa sổ của WebBrowser là cần thiết để lấy lại dấu mũ và tổ hợp phím.
Không nhất quán, hình chữ nhật tiêu điểm chấm chấm xuất hiện quanh WebBrowser (khi tabbing, nhưng không phải khi nhấp). Tôi không thể tìm cách để loại bỏ nó (
FocusVisualStyle="{x:Null}"
không giúp ích gì).Bên trong, WebBrowser không bao giờ nhận được tiêu điểm. Đó là sự thật cho cả hai tập trung hợp lý (FocusManager) và tập trung đầu vào (Keyboard). Các sự kiện
Keyboard.GotKeyboardFocusEvent
vàFocusManager.GotFocusEvent
không bao giờ bị sa thải đối với WebBrowser (mặc dù cả hai đều thực hiện cho các nút trong cùng phạm vi tiêu điểm). Ngay cả khi dấu mũ nằm trong WebBrowser,FocusManager.GetFocusedElement(mainWindow)
trỏ đến phần tử được lấy nét trước đó (một nút) vàKeyboard.FocusedElement
lànull
. Đồng thời,((IKeyboardInputSink)this.webBrowser).HasFocusWithin()
trả vềtrue
.
Tôi muốn nói, hành vi đó gần như quá rối loạn chức năng là đúng, nhưng đó là cách hoạt động của nó. Tôi có thể có thể đến với một số hacks để sửa chữa nó và mang nó liên tiếp với các điều khiển WPF bản địa như TextBox
. Tôi vẫn hy vọng, có lẽ tôi đang thiếu một cái gì đó mơ hồ nhưng đơn giản ở đây. Có ai xử lý một vấn đề tương tự? Bất kỳ đề xuất về cách sửa lỗi này sẽ được đánh giá cao.
Tại thời điểm này, tôi có khuynh hướng phát triển trình bao bọc WPF trong nhà cho Điều khiển WebBrowser ActiveX, dựa trên HwndHost. Chúng tôi cũng là considering other alternatives tới WebBrowser, chẳng hạn như Chromium Embedded Framework (CEF).
Dự án VS2012 có thể được tải xuống từ here trong trường hợp ai đó muốn chơi với nó.
Đây là XAML:
<Window x:Class="WpfWebBrowserTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Width="640" Height="480" Background="LightGray">
<StackPanel Margin="20,20,20,20">
<ToggleButton Name="btnLoad" Focusable="True" IsTabStop="True" Content="Load" Click="btnLoad_Click" Width="100"/>
<WebBrowser Name="webBrowser" Focusable="True" KeyboardNavigation.IsTabStop="True" FocusVisualStyle="{x:Null}" Height="300"/>
<Button Name="btnClose" Focusable="True" IsTabStop="True" Content="Close" Click="btnClose_Click" Width="100"/>
</StackPanel>
</Window>
Đây là mã C#, nó có một loạt các dấu vết chẩn đoán để chứng tỏ sự kiện tiêu điểm/bàn phím được định tuyến và nơi tập trung là:
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows;
using System.Windows.Input;
using System.Windows.Navigation;
namespace WpfWebBrowserTest
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
// watch these events for diagnostics
EventManager.RegisterClassHandler(typeof(UIElement), Keyboard.PreviewKeyDownEvent, new KeyEventHandler(MainWindow_PreviewKeyDown));
EventManager.RegisterClassHandler(typeof(UIElement), Keyboard.GotKeyboardFocusEvent, new KeyboardFocusChangedEventHandler(MainWindow_GotKeyboardFocus));
EventManager.RegisterClassHandler(typeof(UIElement), FocusManager.GotFocusEvent, new RoutedEventHandler(MainWindow_GotFocus));
}
private void btnLoad_Click(object sender, RoutedEventArgs e)
{
// load the browser
this.webBrowser.NavigateToString("<body contentEditable='true' onload='focus()'>Line 1<br>Line 3<br>Line 3<br></body>");
this.btnLoad.IsChecked = true;
}
private void btnClose_Click(object sender, RoutedEventArgs e)
{
// close the form
if (MessageBox.Show("Close it?", this.Title, MessageBoxButton.YesNo) == MessageBoxResult.Yes)
this.Close();
}
// Diagnostic events
void MainWindow_GotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
Debug.Print("{0}, source: {1}, {2}", FormatMethodName(), FormatType(e.Source), FormatFocused());
}
void MainWindow_GotFocus(object sender, RoutedEventArgs e)
{
Debug.Print("{0}, source: {1}, {2}", FormatMethodName(), FormatType(e.Source), FormatFocused());
}
void MainWindow_PreviewKeyDown(object sender, KeyEventArgs e)
{
Debug.Print("{0}, key: {1}, source: {2}, {3}", FormatMethodName(), e.Key.ToString(), FormatType(e.Source), FormatFocused());
}
// Debug output formatting helpers
string FormatFocused()
{
// show current focus and keyboard focus
return String.Format("Focus: {0}, Keyboard focus: {1}, webBrowser.HasFocusWithin: {2}",
FormatType(FocusManager.GetFocusedElement(this)),
FormatType(Keyboard.FocusedElement),
((System.Windows.Interop.IKeyboardInputSink)this.webBrowser).HasFocusWithin());
}
string FormatType(object p)
{
string result = p != null ? String.Concat('*', p.GetType().Name, '*') : "null";
if (p == this.webBrowser)
result += "!!";
return result;
}
static string FormatMethodName()
{
return new StackTrace(true).GetFrame(1).GetMethod().Name;
}
}
}
[UPDATE] Tình huống không tốt hơn nếu tôi lưu trữ WinForms WebBrowser (thay cho, hoặc cạnh nhau với WPF WebBrowser):
<StackPanel Margin="20,20,20,20">
<ToggleButton Name="btnLoad" Focusable="True" IsTabStop="True" Content="Load" Click="btnLoad_Click" Width="100"/>
<WebBrowser Name="webBrowser" Focusable="True" KeyboardNavigation.IsTabStop="True" FocusVisualStyle="{x:Null}" Height="150" Margin="10,10,10,10"/>
<WindowsFormsHost Name="wfHost" Focusable="True" Height="150" Margin="10,10,10,10">
<wf:WebBrowser x:Name="wfWebBrowser" />
</WindowsFormsHost>
<Button Name="btnClose" Focusable="True" IsTabStop="True" Content="Close" Click="btnClose_Click" Width="100"/>
</StackPanel>
Sự cải thiện duy nhất là tôi thấy tập trung vào các sự kiện WindowsFormsHost
.
[UPDATE] Một trường hợp cực đoan: hai điều khiển WebBrowser với hai dấu mũ thể hiện cùng một lúc:
<StackPanel Margin="20,20,20,20">
<ToggleButton Name="btnLoad" Focusable="True" IsTabStop="True" Content="Load" Click="btnLoad_Click" Width="100"/>
<WebBrowser Name="webBrowser" Focusable="True" KeyboardNavigation.IsTabStop="True" FocusVisualStyle="{x:Null}" Height="150" Margin="10,10,10,10"/>
<WebBrowser Name="webBrowser2" Focusable="True" KeyboardNavigation.IsTabStop="True" FocusVisualStyle="{x:Null}" Height="150" Margin="10,10,10,10"/>
<Button Name="btnClose" Focusable="True" IsTabStop="True" Content="Close" Click="btnClose_Click" Width="100"/>
</StackPanel>
this.webBrowser.NavigateToString("<body onload='text.focus()'><textarea id='text' style='width: 100%; height: 100%'>text</textarea></body>");
this.webBrowser2.NavigateToString("<body onload='text.focus()'><textarea id='text' style='width: 100%; height: 100%'>text2</textarea></body>");
này cũng cho thấy việc xử lý vấn đề trọng tâm là không cụ thể cho contentEditable=true
nội dung.
Cả WPF lẫn HTML đều đổ lỗi ở đây. Cả điều khiển WebBrowser của WPF đều đủ trưởng thành để xử lý tập trung đúng cách, cũng như không thể chỉnh sửa nội dung của HTML là tập trung thân thiện. Tôi đã sửa các vấn đề tiêu điểm tương tự với WebBrowser của WPF bằng cách thêm
@digitguy, cảm ơn bạn. Tôi hiện đang chơi với một giải pháp tương tự: gói WebBrowser với UserControl, gọi InvokeScript ("focus") theo cách thủ công và xử lý các cửa sổ HTML bên trong sự kiện onfocus/onblur để đặt WPF tập trung vào UserControl cho phù hợp. Sẽ đăng ở đây những gì tôi sẽ đưa ra. Có vẻ như vấn đề caret không cụ thể đối với 'contentEditable = true', điều tương tự cũng áp dụng cho' textarea' hoặc 'input type = text'. – Noseratio
Tôi muốn liên kết [this] (http://stackoverflow.com/questions/18437898/why-is-keyboard-focusedelement-null-when-focus-is-inside-windowsformshost-it-br) và [điều này ] (http://stackoverflow.com/questions/18417648/inconsistency-in-wpf-command-routing-behavior-depending-on-the-ui-focus-state) các câu hỏi ở đây như là một phần của nghiên cứu của tôi về chủ đề này. – Noseratio