我有一个文本块和一个webbrowser控件。我有一个问题,例如,我的webbrowser导航到了google.com。当webbrowser导航到google.com时,我希望文本块的标题更改为google.com。
请帮助我使用c#实现此功能。
已在IE上测试过
XAML:
<Grid>
<WebBrowser LoadCompleted="webBrowser1_LoadCompleted" Height="100" HorizontalAlignment="Left" Margin="73,72,0,0" Name="webBrowser1" VerticalAlignment="Top" Width="200" />
<Button Content="Go" Click="Button_Click" HorizontalAlignment="Right" VerticalAlignment="Bottom"/>
</Grid>
代码:
private void webBrowser1_LoadCompleted(object sender, NavigationEventArgs e)
{
dynamic doc = webBrowser1.Document;
this.Title = doc.Title;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
webBrowser1.Navigate("http://google.com");
}
没有动态和几乎没有异常处理:
private void webBrowser1_LoadCompleted(object sender, NavigationEventArgs e)
{
Object doc = webBrowser1.Document;
this.Title = GetPropertyValue<string>(doc, "Title");
}
private T GetPropertyValue<T>(object obj, string propertyName)
{
Type objectType = obj.GetType();
PropertyInfo propertyInfo = objectType.GetProperty(propertyName);
Type propertyType = propertyInfo.PropertyType;
if(propertyType == typeof(T))
{
object propertyValue = (T)info.GetValue(obj, null);
return value;
}
else
{
throw new Exception("Property " + propertyName + " is not of type " + T);
}
}
您可以从WebBrowser的Text
属性中提取标题标签,只需订阅LoadCompleted
事件即可。
Document.Title属性存在问题,如果在JavaScript中设置或更改标题,则一旦设置,您将无法获得最新值。
我们使用FormsHost而不是WPF中的默认Web浏览器,并且使用Windows窗体的Web浏览器,该浏览器支持DocumentTitle属性和DocumentTitleChanged事件。
因此,我建议使用以下控件,您可以使用更多在窗体版本中可用的功能。如果仔细注意,两者在性能方面完全相同,因为两者都创建一个Win32控件并与其交互。
public class FormsWebBrowser :
System.Windows.Forms.Integration.WindowsFormsHost
{
System.Windows.Forms.WebBrowser Browser =
new System.Windows.Forms.WebBrowser();
public FormsWebBrowser()
{
Child = Browser;
Browser.DocumentTitleChanged +=
new EventHandler(Browser_DocumentTitleChanged);
}
void Browser_DocumentTitleChanged(object sender, EventArgs e)
{
this.DocumentTitle = Browser.DocumentTitle;
}
///<summary>
/// This will let you bind
///</summary>
public string DocumentTitle
{
get { return (string)GetValue(DocumentTitleProperty); }
private set { SetValue(DocumentTitleProperty, value); }
}
public static readonly DependencyProperty DocumentTitleProperty =
DependencyProperty.Register("DocumentTitle", typeof(string),
typeof(FormsWebBrowser), new FrameworkPropertyMetadata(""));
}
可能需要一些额外的代码来实现一些小功能,但是通过添加更多的依赖属性和控制逻辑,一切都是可能的。
针对Erno de Weerd的答案,仅进行了一些微小的拼写修正,适用于.NET 4.5 *) 属性名称为IHTMLDocument2_nameProp *) 在if块中修正了拼写错误
private void webBrowser1_LoadCompleted(object sender, NavigationEventArgs e)
{
Object doc = webBrowser1.Document;
this.Title = GetPropertyValue<string>(doc, "IHTMLDocument2_nameProp");
}
private T GetPropertyValue<T>(object obj, string propertyName)
{
Type objectType = obj.GetType();
PropertyInfo propertyInfo = objectType.GetProperty(propertyName);
Type propertyType = propertyInfo.PropertyType;
if(propertyType == typeof(T))
{
object alue = (T)propertyInfo.GetValue(obj, null);
return value;
}
else
{
throw new Exception("Property " + propertyName + " is not of type " + T);
}
}
这个会起作用
var docTitle = document.getElementsByTagName("title")
.Cast<IHTMLElement>()
.FirstOrDefault().innerText;
<Window Title={Binding Path=Title}>
然后将窗口的上下文设置为浏览器或类似的东西?或者你可能可以给 WebBrowser 命名,而不设置窗口的 DataContext。 - AlxandrTitle="{Binding ElementName=webBrowser1, Path=Document.Title}"
,那么据我所知不行,因为文档的 Title 属性不会引发 PropertyChanged 事件,所以绑定不会被更新。 - Emonddynamic
的示例。警告:我省略了异常处理并且没有测试过这个代码。 - Emond