• 基于CefSharp开发浏览器(九)浏览器历史记录弹窗面板


    一、前言

    前两篇文章写的是关于浏览器收藏夹的内容,因为收藏夹的内容不会太多,故采用json格式的文本文件作为收藏夹的存储方式。

    关于浏览器历史记录,我个人每天大概会打开百来次网页甚至更多,时间越长历史记录会越多多。此时使用json存储一旦数据量加大,势必会影响效率。

    故需要选择一个新的存储方式。展开思考:Edge是用什么存储的呢?

    二、探究Edge历史记录存储方式

    经过几番查找终于找到Edge数据存储位置:C:Users用户AppDataLocalMicrosoftEdgeUser DataDefault

    浏览一下看看是否有所需的文件,咦?发现了Bookmarks,这应该是存储收藏夹数据的吧,尝试打开看看

    使用Notepad++打开看看,咦,这不巧了吗?竟然也是json存储。和之前收藏夹的存储想法不谋而合。

    Edge历史记录该不会也是json存储吧? 令人担忧

    继续浏览该目录,这应该就是保存历史记录的

     打开看看:

     心里松了一口气,还好不是Json。

    那究竟是怎样存储的呢?可以看到该文件的第一行 “SQLite format”,它可能是一个SQLite数据库文件。

    使用SQLiteSpy打开看看,A我去了,果然是SQLite数据库文件。

    个人猜测 Downloads存储的是下载历史,keyword_search_terms是搜索历史

    visit存储访问历史,也就是我们所需要的历史记录。打开visit,

    虽然没直接存储url,但有url的id,打开urls表

    揍是它,到此可以得出:Edge的历史记录存储在SQLite 格式的文件中。那好,我们也使用SQLite作为历史记录的存储方式。

    三、数据存储设计

    上面已分析出Edge的历史记录存储方式,这里照葫芦画瓢也采用SQLite存储数据。

    ORM框架选型,.Net 的ORM框架有很多。如SqlSugar、Dos.ORM、Entity Framework 、NHibernate等等。

    近两年 SqlSugar总体评价较好,这里采用SqlSugar,官方文档:http://donet5.com/Home/Doc

    NuGet Package Manager中添加 SqlSugarCore引用:

    新建HistoryModel 用户存储历史记录,目前只建一张表。后期有需要在按需扩展。

    [SugarTable("history", "f10")]
    public class HistoryModel
    {
        [SugarColumn(ColumnName = "id", IsPrimaryKey = true, IsIdentity = true)]
        public int Id { get; set; }
        public string Title { get; set; }
        public string Url { get; set; }
        public DateTime VisitTime { get; set; }
        public int FormVisit { get; set; }
    }

    新建 DbContext用于配置 SqlSugarClient

    public class DbContext
    {
        private SqlSugarClient _db;
        public SqlSugarClient Db
        {
            get => _db;
            private set => _db = value;
        }
        public DbContext()
        {
            string connStr = $"DataSource={Environment.CurrentDirectory}\History.db";
            ConnectionConfig config = new ConnectionConfig
            {
                ConnectionString = connStr,
                DbType = DbType.Sqlite,
                InitKeyType = InitKeyType.Attribute,
                IsAutoCloseConnection = true,
            };
            _db = new SqlSugarClient(config);
        }
    }

    新建 DbSeed用于数据库初始化

    public static class DbSeed
    {
        private static readonly DbContext _context;
        static DbSeed()
        {
            _context = new DbContext();
        }
        public static void InitData()
        {
            //创建数据库
            _context.Db.DbMaintenance.CreateDatabase();
    
            //创建表,反射获取指定数据表
            var modelTypes = from table in Assembly.GetExecutingAssembly().GetTypes()
                where table.IsClass && table.Namespace == "Cys_Model.Tables"
                select table;
    
            foreach (var t in modelTypes.ToList())
            {
                if (_context.Db.DbMaintenance.IsAnyTable(t.Name)) continue;
                _context.Db.CodeFirst.InitTables(t);
            }
        }
    }

    四、历史记录界面设计

    首先看看Edge历史记录弹窗面板,如图所示:

     可分为上下两部分

    上半部分分为搜索,子菜单,固定到右侧(本章暂不处理)

    下半部分为数据列表(本章完成这一部分)

     Edge的历史记录弹窗面板的外部展示方式与收藏夹菜单类似也是弹窗,可以采用Popup实现。新建HistoryUc用户控件,代码如下:

    <UserControl x:Class="MWebBrowser.View.HistoryUc"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                 xmlns:history="clr-namespace:MWebBrowser.View.History"
                 mc:Ignorable="d" d:DesignHeight="30" d:DesignWidth="40">
        <Grid>
            <Grid.Resources>
                <DataTemplate x:Key="ListBoxTemplate">
                    <history:HistoryItemUc/>
                </DataTemplate>
            </Grid.Resources>
            <ToggleButton x:Name="HistoryButton" Style="{DynamicResource ToggleButton.FontButton}" Checked="HistoryButton_OnChecked"
                          Unchecked="HistoryButton_OnUnchecked" Content="&#xe786;" FontSize="32" Background="Transparent" IsChecked="{Binding ElementName=FavoritesPop,Path=IsOpen}"/>
            <Popup x:Name="FavoritesPop" PopupAnimation="Fade" Placement="Bottom"  PlacementTarget="{Binding ElementName=FavoritesButton}"
                   StaysOpen="False" AllowsTransparency="True" HorizontalOffset="-330">
                <Border x:Name="PopBorder" Background="{DynamicResource WebBrowserBrushes.WebMenuBackground}" CornerRadius="5">
                    <Border.Effect>
                        <DropShadowEffect Color="{DynamicResource Color.MenuItemDropShadowBrush}" Opacity="0.3" ShadowDepth="3"/>
                    </Border.Effect>
                    <Grid Width="360" Height="660">
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto"/>
                            <RowDefinition Height="1"/>
                            <RowDefinition Height="*"/>
                        </Grid.RowDefinitions>
                        <Grid Grid.Row="0" Height="40">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="Auto"/>
                                <ColumnDefinition Width="*"/>
                                <ColumnDefinition Width="Auto"/>
                            </Grid.ColumnDefinitions>
                            <TextBlock Grid.Column="0" Text="历史记录" VerticalAlignment="Center" FontSize="18" Margin="10,0,0,0" Foreground="{DynamicResource WebBrowserBrushes.DefaultForeground}"/>
                        </Grid>
                        <Rectangle Grid.Row="1" Height="1" Fill="{DynamicResource WebBrowserBrushes.WebMenuDivideLine}"/>
                        <ListBox Grid.Row="2" x:Name="HistoryListBox" ItemsSource="{Binding HistoryList}" Background="Transparent" ItemTemplate="{StaticResource ListBoxTemplate}" Style="{DynamicResource CustomListBox.HistoryListBox}"/>
                    </Grid>
                </Border>
            </Popup>
        </Grid>
    </UserControl>
    View Code

    HistoryButton 控制Popup开闭。Popup中 添加 ListBox用于展示数据列

    HistoryUc.xaml.cs代码:

    using Cys_Controls.Code;
    using MWebBrowser.ViewModel;
    using System.Windows.Controls;
    
    namespace MWebBrowser.View
    {
        /// <summary>
        /// Interaction logic for HistoryUc.xaml
        /// </summary>
        public partial class HistoryUc : UserControl
        {
            private readonly HistoryViewModel _viewModel;
            private double _offset;
            public HistoryUc()
            {
                InitializeComponent();
                _viewModel = new HistoryViewModel();
                this.DataContext = _viewModel;
                HistoryListBox.DataContext = _viewModel;
            }
            private void ScrollChanged(object sender, ScrollChangedEventArgs e)
            {
                if (!(sender is ScrollViewer scrollViewer)) return;
                if (_offset > scrollViewer.VerticalOffset) return;
                _offset = scrollViewer.VerticalOffset;
                if ((int)scrollViewer.VerticalOffset >= (scrollViewer.ScrollableHeight - 3))
                {
                    _viewModel.GetHistoryList();
                }
            }
            private void HistoryButton_OnChecked(object sender, System.Windows.RoutedEventArgs e)
            {
                _viewModel.ReSet();
                _viewModel.GetHistoryList();
                ScrollViewer sv = ControlHelper.FindVisualChild<ScrollViewer>(HistoryListBox);
                if (sv != null)
                {
                    sv.ScrollChanged -= ScrollChanged;
                    sv.ScrollChanged += ScrollChanged;
                }
            }
    
            private void HistoryButton_OnUnchecked(object sender, System.Windows.RoutedEventArgs e)
            {
    
            }
        }
    }
    View Code

    这里需要注意由于历史记录比较多,故需要采用分页处理,当前采用的是滚动条即将触底时获取数据,每次获取20条。 

    需要自定义ListBoxItem的外观,创建HistoryItemUc

    <UserControl x:Class="MWebBrowser.View.History.HistoryItemUc"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                 mc:Ignorable="d" 
                 d:DesignHeight="40" d:DesignWidth="400">
        <Grid Height="40">
            <!--<TextBlock Text="{Binding PublishTimeStr}" FontWeight="Bold" FontSize="16" Foreground="#FFFFFF" Visibility="{Binding GroupVisible}"/>-->
            <Grid>
                <Grid Margin="5,0">
                    <Border Margin="0,0,20,0" MaxWidth="350" CornerRadius="5" Background="{Binding BackColorBrush}"  MouseEnter="History_OnMouseEnter" MouseLeave="History_OnMouseLeave" MouseLeftButtonDown="History_OnMouseLeftButtonDown" Cursor="Hand">
                        <Grid Margin="10,0">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="Auto"/>
                                <ColumnDefinition Width="*"/>
                                <ColumnDefinition Width="Auto"/>
                            </Grid.ColumnDefinitions>
                            <Image Width="16" Height="16" Grid.Column="0" Source="{Binding Favicon}"/>
                            <TextBlock Margin="10,0,0,0" Grid.Column="1" FontSize="14" TextTrimming="CharacterEllipsis" Foreground="#FFFFFF" Text="{Binding Title}"  HorizontalAlignment="Left" VerticalAlignment="Center"/>
                            <TextBlock TextTrimming="CharacterEllipsis" Margin="10,0,0,0" Visibility="{Binding DateVisible}" Grid.Column="2" Text="{Binding VisitTimeStr}" VerticalAlignment="Center" Foreground="{DynamicResource WebBrowserBrushes.HistoryDateForeground}"/>
                            <Button Visibility="{Binding CloseVisible}" Grid.Column="2" Margin="10,0,0,0" Style="{DynamicResource Button.DownloadCloseButton}" Click="Delete_OnClick" VerticalAlignment="Center"/>
                        </Grid>
                    </Border>
                </Grid>
            </Grid>
        </Grid>
    </UserControl>
    View Code

    HistoryItemUc.xaml.cs代码如下:

    using Cys_Controls.Code;
    using MWebBrowser.ViewModel;
    using System;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Input;
    using System.Windows.Media;
    
    namespace MWebBrowser.View.History
    {
        /// <summary>
        /// Interaction logic for HistoryItemUc.xaml
        /// </summary>
        public partial class HistoryItemUc : UserControl
        {
            public HistoryItemUc()
            {
                InitializeComponent();
            }
    
            private void History_OnMouseEnter(object sender, MouseEventArgs e)
            {
                if (!(this.DataContext is HistoryItemViewModel viewModel)) return;
    
                viewModel.BackColorBrush = Application.Current.MainWindow?.FindResource("WebBrowserBrushes.HistoryBackgroundOver") as SolidColorBrush;
                viewModel.DateVisible = Visibility.Collapsed;
                viewModel.CloseVisible = Visibility.Visible;
            }
    
            private void History_OnMouseLeave(object sender, MouseEventArgs e)
            {
                if (!(this.DataContext is HistoryItemViewModel viewModel)) return;
    
                viewModel.BackColorBrush = Application.Current.MainWindow?.FindResource("WebBrowserBrushes.HistoryBackground") as SolidColorBrush;
                viewModel.DateVisible = Visibility.Visible;
                viewModel.CloseVisible = Visibility.Collapsed;
            }
    
            private void History_OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
            {
                if (!(this.DataContext is HistoryItemViewModel viewModel)) return;
                try
                { 
                   var uc = ControlHelper.FindVisualChild<WebTabControlUc>(Application.Current.MainWindow);
                   uc.TabItemAdd(viewModel.Url);
                }
                catch (Exception ex)
                {
                
                }
            }
    
            private void Delete_OnClick(object sender, RoutedEventArgs e)
            {
                if (!(this.DataContext is HistoryItemViewModel viewModel)) return;
                var uc = ControlHelper.FindVisualChild<WebTabControlUc>(Application.Current.MainWindow);
                var historyUc = ControlHelper.FindVisualChild<HistoryUc>(uc);
                if (historyUc?.DataContext is HistoryViewModel hvm)
                {
                    hvm.DeleteHistoryItem(viewModel);
                }
            }
        }
    }
    View Code

    五、运行效果

     

    五、源码地址

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

    项目邀请:如对该项目有兴趣,欢迎联系我共同开发!!!

    天行健,君子以自强不息; 地势坤,君子以厚德载物;
  • 相关阅读:
    scala之 spark连接SQL和HIVE/IDEA操作HDFS
    hive之 连接DBeaver
    hive之 配置的图解
    Hive和sparksql中的dayofweek
    spark SQL之 DataFrame使用
    spark SQL之 org.apache.spark.sql.AnalysisException: Table or view not found:
    Spring详解(七)------AOP 注解
    Spring详解(六)------AspectJ 实现AOP
    Spring详解(五)------面向切面编程
    Spring详解(十)------spring 环境切换
  • 原文地址:https://www.cnblogs.com/mchao/p/14478602.html
Copyright © 2020-2023  润新知