zoukankan      html  css  js  c++  java
  • 基于CefSharp开发浏览器(三)浏览器头部优化

    一、上文回顾

    上编实现了简单的网页加载功能包括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

    四、源码地址

    gitee地址:https://gitee.com/sirius_machao/mweb-browser

  • 相关阅读:
    day5_python之hashlib模块
    day6_python之pickle、shelve序列化和反序列化
    day6_python之json序列化和反序列化
    day6_python之configparser_模块
    day1_python之字符串的常用操作
    day6_python序列化之 json & pickle & shelve 模块
    python如何自动发送邮件
    python selenium 获取对象输入的属性值
    python selenium 处理悬浮窗口(baidu tj_more)
    python selenium处理JS只读(12306)
  • 原文地址:https://www.cnblogs.com/mchao/p/13931100.html
Copyright © 2011-2022 走看看