一、上文回顧
上編實現了簡單的網頁加載功能包括URL輸入、打開空標簽頁、網頁鏈接中新頁面處理等
本編將對網頁的Title綁定、前進、后退、刷新等事件處理
二、Title綁定處理
當打開網頁時Title一直是新標簽頁,而Edge瀏覽器中是動態變化的,因此我們需要建立起綁定機制,那么如何取網頁Title?
查看ChromiumWebBrowser 類定義
public static readonly DependencyProperty TitleProperty;
發現其有Title的依賴屬性,並在類定義中找到了 TitleChanged事件
public event DependencyPropertyChangedEventHandler TitleChanged;
因此只要將Tab頁的Header屬性與ChromiumWebBrowser類中的Title建立起關系就可以
創建 WebTabItemViewModel 添加 Header屬性
public class WebTabItemViewModel: BaseViewModel { private string _title = "新標簽頁";
public string Title{ get =>_title ; set { _title = value; OnPropertyChanged("Title"); } }
}
在TitleChanged 改變時賦值給Header
private void CefWebBrowser_TitleChanged(object sender, DependencyPropertyChangedEventArgs e) { ViewModel.Title= CefWebBrowser.Title; }
並在新打開Tab頁時建立綁定
private void TabItemAdd(object obj) { try { var uc = new WebTabItemUc { TargetUrl = obj?.ToString() }; var item = new TabItem { Content = uc }; var bind = new Binding { Source = uc.DataContext, Path = new PropertyPath("Header") }; item.SetBinding(HeaderedContentControl.HeaderProperty, bind); WebTabControl.Items.Add(item); WebTabControl.SelectedItem = item; WebTabControl.SetHeaderPanelWidth(); } catch (Exception ex) { } }
此處可以直接綁定ChromiumWebBrowser 的Title屬性,但為了能使當打開新Tab頁時顯示【新標簽頁】所以做了個ViewModel處理
運行看下效果
此時Title還缺個Favicon,Favicon 格式為協議+域名+端口+/favicon.ico
如百度https://www.baidu.com/favicon.ico
故增加favicon獲取方法
private ImageSource GetFavicon() { try { var pattern = @"(\w+:\/\/)([^/:]+)(:\d*)?"; var address = CefWebBrowser.Address; var matches = Regex.Matches(address, pattern); return matches.Count <= 0 ? null : ImageHelper.GetBitmapFrame($"{matches[0]}/favicon.ico"); } catch (Exception e) { return ImageHelper.DefaultFavicon; } }
public static ImageSource GetBitmapFrame(string httpUrl) { try { return string.IsNullOrEmpty(httpUrl) ? DefaultFavicon : BitmapFrame.Create(new Uri(httpUrl), BitmapCreateOptions.None, BitmapCacheOption.Default); } catch { return DefaultFavicon; }
並暫時將此方法加到Browser Title改變事件中
private void CefWebBrowser_TitleChanged(object sender, DependencyPropertyChangedEventArgs e) { ViewModel.Title = CefWebBrowser.Title; ViewModel.Favicon = GetFavicon(); }
接下來需要對ViewModel中Favicon 進行界面綁定關聯
此時需要對Tabitem進行擴展這里使用附加屬性來綁定Favicon
<Grid HorizontalAlignment="{TemplateBinding HorizontalAlignment}"> <Grid.ColumnDefinitions> <ColumnDefinition Width="auto"/> <ColumnDefinition Width="*"/> <ColumnDefinition Width="auto"/> </Grid.ColumnDefinitions> <Image x:Name="PART_Favicon" Grid.Column="0" Source="{TemplateBinding attached:AttachedPropertyClass.ImageSource}" Width="18" Height="18"/> <ContentPresenter Grid.Column="1" x:Name="contentPresenter" ContentSource="Header" Focusable="False" HorizontalAlignment="Left" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="Center"> <ContentPresenter.Resources> <Style TargetType="{x:Type TextBlock}"> <Setter Property="FontSize" Value="14"/> <Setter Property="TextTrimming" Value="CharacterEllipsis"/> <!--不知為什么直接在tabitem中設置fontsize不起作用--> </Style> </ContentPresenter.Resources> </ContentPresenter> <Button Grid.Column="2" Style="{StaticResource TabCloseButton}" Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:MTabControl}},Path=TabItemRemoveCommand}" CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type TabItem}}}" /> </Grid>
Xaml中 PART_Favicon 綁定附加屬性 ImageSource接下來對附加屬性與ViewModel中的Favicon進行綁定
在TabItemAdd方法中增加綁定
private void TabItemAdd(object obj) { try { var uc = new WebTabItemUc { ViewModel = { CurrentUrl = obj?.ToString() } }; var item = new TabItem { Content = uc }; var titleBind = new Binding { Source = uc.DataContext, Path = new PropertyPath("Title") }; item.SetBinding(HeaderedContentControl.HeaderProperty, titleBind); var faviconBind = new Binding { Source = uc.DataContext, Path = new PropertyPath("Favicon") }; item.SetBinding(AttachedPropertyClass.ImageSourceProperty, faviconBind); WebTabControl.Items.Add(item); WebTabControl.SelectedItem = item; WebTabControl.SetHeaderPanelWidth(); } catch (Exception ex) { } }
再次運行程序
三、前進、后退、刷新處理
前進、后退、刷新是IWebBrowser的擴展方法 在WebBrowserExtensions類中
分別添加按鈕的響應事件如下
private void NavigationForward_OnClick(object sender, RoutedEventArgs e) { this.CefWebBrowser.Forward(); } private void NavigationBack_OnClick(object sender, RoutedEventArgs e) { this.CefWebBrowser.Back(); } private void NavigationRefresh_OnClick(object sender, RoutedEventArgs e) { this.CefWebBrowser.Reload(); }
綁定前進后退按鈕可用狀態 分別為CanGoForward、CanGoBack
<StackPanel Grid.Column="0" Orientation="Horizontal" x:Name="NavigationStackPanel"> <Button Style="{DynamicResource Button.NavigationBack}" IsEnabled="{Binding CanGoBack}" Click="NavigationBack_OnClick"/> <Button Style="{DynamicResource Button.NavigationForward}" IsEnabled="{Binding CanGoForward}" Click="NavigationForward_OnClick"/> <Button Style="{DynamicResource Button.NavigationRefresh}" Click="NavigationRefresh_OnClick"/> </StackPanel>
在cs代碼中進行 NavigationStackPanel的上下文綁定
NavigationStackPanel.DataContext = CefWebBrowser;
此處我們直接綁定ChromiumWebBrowser 的依賴屬性,故DataContext賦值為 CefWebBrowser