基於CefSharp開發瀏覽器(九)瀏覽器歷史記錄彈窗面板


一、前言

前兩篇文章寫的是關於瀏覽器收藏夾的內容,因為收藏夾的內容不會太多,故采用json格式的文本文件作為收藏夾的存儲方式。

關於瀏覽器歷史記錄,我個人每天大概會打開百來次網頁甚至更多,時間越長歷史記錄會越多多。此時使用json存儲一旦數據量加大,勢必會影響效率。

故需要選擇一個新的存儲方式。展開思考:Edge是用什么存儲的呢?

二、探究Edge歷史記錄存儲方式

經過幾番查找終於找到Edge數據存儲位置:C:\Users\用戶\AppData\Local\Microsoft\Edge\User Data\Default

瀏覽一下看看是否有所需的文件,咦?發現了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

項目邀請:如對該項目有興趣,歡迎聯系我共同開發!!!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM