循序漸進介紹基於CommunityToolkit.Mvvm 和HandyControl的WPF應用端開發(4) -- 實現DataGrid數據的導入和導出操作

来源:https://www.cnblogs.com/wuhuacong/archive/2023/09/18/17711356.html
-Advertisement-
Play Games

在我們設計軟體的很多地方,都看到需要對錶格數據進行導入和導出的操作,主要是方便客戶進行快速的數據處理和分享的功能,本篇隨筆介紹基於WPF實現DataGrid數據的導入和導出操作。 ...


在我們設計軟體的很多地方,都看到需要對錶格數據進行導入和導出的操作,主要是方便客戶進行快速的數據處理和分享的功能,本篇隨筆介紹基於WPF實現DataGrid數據的導入和導出操作。

1、系統界面設計

在我們實現數據的導入導出功能之前,我們在主界面需要提供給客戶相關的操作按鈕,如下界面所示,在列表的頂端提供導入Excel、導出PDF、導出Excel。

由於這些操作功能基本上在各個頁面模塊,可能都會用到,因此儘可能的抽象到基類,以及提供通用的處理操作,實在有差異的,也可以通過一些屬性或者事件方法的覆蓋方式來實現即可。

因此我們在Xaml裡面定義按鈕的時候,基本上是調用視圖模型的方法來通用化的處理,如下代碼所示。

<Button
    Margin="5"
    hc:IconElement.Geometry="{StaticResource t_import}"
    Command="{Binding ImportExcelCommand}"
    Content="導入Excel"
    Style="{StaticResource ButtonWarning}" />
<Button
    Margin="5"
    hc:IconElement.Geometry="{StaticResource SaveGeometry}"
    Command="{Binding ViewModel.ExportPdfCommand}"
    CommandParameter="用戶信息列表"
    Content="導出PDF"
    Style="{StaticResource ButtonSuccess}" />
<Button
    Margin="5"
    hc:IconElement.Geometry="{StaticResource SaveGeometry}"
    Command="{Binding ViewModel.ExportExcelCommand}"
    CommandParameter="用戶信息列表"
    Content="導出Excel"
    Style="{StaticResource ButtonSuccess}" />

而導入的處理操作函數ImportExcelComand的定義如下所示(註意這裡聲明瞭RelayCommand)代碼會自動生成Command的尾碼Command方法的。

    /// <summary>
    /// 導出內容到Excel
    /// </summary>
    [RelayCommand]
    private void ImportExcel()
    {
        var page = App.GetService<ImportExcelData>();
        page!.ViewModel.Items?.Clear();
        page!.ViewModel.TemplateFile = $"系統用戶信息-模板.xls";
        page!.OnDataSave -= ExcelData_OnDataSave;
        page!.OnDataSave += ExcelData_OnDataSave;

        //導航到指定頁面
        ViewModel.Navigate(typeof(ImportExcelData));
    }

而其中 ImportExcelData 是我們定義的通用導入頁面窗體類,這裡只需要實現一些屬性的設置(根據子類的不同而調整,後期可以用代碼生成工具生成),以及一些事件用於子類延後實現,從而可以實現自定義的數據處理的功能。

我們在下麵再細說批量導入的處理細節。

 

2、數據導出到Excel

數據導出到Excel,在我們的Winform端中很常見,而WPF這裡也是一樣的處理方式,通用利用Excel的操作組件的封裝類來實現,可以基於NPOI,也可以基於Aspose.Cell實現,根據自己的需要實現簡單的封裝調用即可。

導出到Excel,首先需要彈出選擇目錄的對話框進行選取目錄,然後用於生成Excel的文件,如下界面所示。

這個處理,由於WPF可以調用.net裡面的System.Windows.Forms,因此我們直接調用裡面的對話框處理封裝即可,這個類來自於我們的Winform的UI公用類庫部分。

在前面隨筆,我們介紹過為了WPF開發的方便,我們設計了幾個視圖基類,用於減少代碼的處理。

對於不同的業務類,我們也只需要根據實際情況,生成對應的業務視圖模型類即可。

我們把通用的導出操作放到了這個視圖基類BaseListViewModel 裡面即可,如下代碼所示。

/// <summary>
/// 觸發導出Excel處理命令
/// </summary>
[RelayCommand]
protected virtual async Task ExportExcel(string title = "列表數據")
{
    var table = await this.ConvertItems(this.Items);
    BaseExportExcel(table, title);
}

而其中對於DataTable的處理Excel,提供一個通用的方法。

    /// <summary>
    /// 可供重寫的基類函數,導出Excel
    /// </summary>
    public virtual void BaseExportExcel(DataTable table, string title = "列表數據")
    {
        string file = FileDialogHelper.SaveExcel(string.Format("{0}.xls", title));
        if (!string.IsNullOrEmpty(file))
        {
            try
            {
                string error = "";
                AsposeExcelTools.DataTableToExcel2(table, file, out error);

                if (!string.IsNullOrEmpty(error))
                {
                    MessageDxUtil.ShowError(string.Format("導出Excel出現錯誤:{0}", error));
                }
                else
                {
                    if (MessageDxUtil.ShowYesNoAndTips("導出成功,是否打開文件?") == System.Windows.MessageBoxResult.Yes)
                    {
                        Process.Start("explorer.exe", file);
                    }
                }
            }
            catch (Exception ex)
            {
                LogTextHelper.Error(ex);
                MessageDxUtil.ShowError(ex.Message);
            }
        }
    }

其中FileDialogHelper.SaveExcel 的代碼如下所示。

/// <summary>
/// 保存Excel對話框,並返回保存全路徑
/// </summary>
/// <returns></returns>
public static string SaveExcel(string filename, string initialDirectory)
{
    return Save("保存Excel", ExcelFilter, filename, initialDirectory);
} 

/// <summary>
/// 以指定的標題彈出保存文件對話框
/// </summary>
/// <param name="title">對話框標題</param>
/// <param name="filter">尾碼名過濾</param>
/// <param name="filename">預設文件名</param>
/// <param name="initialDirectory">初始化目錄</param>
/// <returns></returns>
public static string Save(string title, string filter, string filename, string initialDirectory)
{
    //多語言支持
    title = JsonLanguage.Default.GetString(title);

    var dialog = new SaveFileDialog();
    dialog.Filter = filter;
    dialog.Title = title;
    dialog.FileName = filename;
    dialog.RestoreDirectory = true;
    if (!string.IsNullOrEmpty(initialDirectory))
    {
        dialog.InitialDirectory = initialDirectory;
    }

    if (dialog.ShowDialog() == DialogResult.OK)
    {
        return dialog.FileName;
    }
    return string.Empty;
}

而其中SaveFileDialog是屬於.net 中System.Windows.Forms裡面的內容,WPF可以直接調用。

而DataTableToExcel2 方法,這是我們封裝的一個使用Aspose.Cell的調用,主要用於快速處理DataTable到Excel的操作封裝,我們也可可以利用其它操作Excel的封裝,如NPOI等都可以實現。

代碼如下所示。

/// <summary>
/// 把DataTabel轉換成Excel文件
/// </summary>
/// <param name="datatable">DataTable對象</param>
/// <param name="filepath">目標文件路徑,Excel文件的全路徑</param>
/// <param name="error">錯誤信息:返回錯誤信息,沒有錯誤返回""</param>
/// <returns></returns>
public static bool DataTableToExcel2(DataTable datatable, string filepath, out string error)
{
    error = "";
    var wb = new Aspose.Cells.Workbook();

    try
    {
        if (datatable == null)
        {
            error = "DataTableToExcel:datatable 為空";
            return false;
        }

        //為單元格添加樣式    
        var style = wb.CreateStyle();
        //設置居中
        style.HorizontalAlignment = Aspose.Cells.TextAlignmentType.Center;
        //設置背景顏色
        style.ForegroundColor = System.Drawing.Color.FromArgb(153, 204, 0);
        style.Pattern = BackgroundType.Solid;
        style.Font.IsBold = true;

        int rowIndex = 0;
        for (int i = 0; i < datatable.Columns.Count; i++)
        {
            DataColumn col = datatable.Columns[i];
            string columnName = col.Caption ?? col.ColumnName;
            wb.Worksheets[0].Cells[rowIndex, i].PutValue(columnName);
            wb.Worksheets[0].Cells[rowIndex, i].SetStyle(style);
        }
        rowIndex++;

        foreach (DataRow row in datatable.Rows)
        {
            for (int i = 0; i < datatable.Columns.Count; i++)
            {
                wb.Worksheets[0].Cells[rowIndex, i].PutValue(row[i].ToString());
            }
            rowIndex++;
        }

        for (int k = 0; k < datatable.Columns.Count; k++)
        {
            wb.Worksheets[0].AutoFitColumn(k, 0, 150);
        }
        wb.Worksheets[0].FreezePanes(1, 0, 1, datatable.Columns.Count);
        wb.Save(filepath);
        return true;
    }
    catch (Exception e)
    {
        error = error + " DataTableToExcel: " + e.Message;
        return false;
    }

}

導出Excel的內容如下界面所示。另外導出文檔的內容,我們可以用於導入的數據模板的。

我們可以根據需要設置要導出的列即可。

 

3、數據導出到PDF

同樣,數據導出到PDF的處理操作類似,也是通過視圖基類的封裝方法,實現快速的導出到PDF處理,如下是視圖基類裡面的實現方法。

/// <summary>
/// 觸發導出PDF處理命令
/// </summary>
[RelayCommand]
protected virtual async Task ExportPdf(string title = "列表數據")
{
    var table = await this.ConvertItems(this.Items);
    BaseExportPdf(table, title);
}

/// <summary>
/// 可供重寫的基類函數,導出PDF
/// </summary>
public virtual void BaseExportPdf(DataTable table, string title = "列表數據")
{
    var pdfFile = FileDialogHelper.SavePdf();
    if (!pdfFile.IsNullOrEmpty())
    {
        bool isLandscape = true;//是否為橫向列印,預設為true
        bool includeHeader = true;//是否每頁包含表頭信息
        var headerAlignment = iText.Layout.Properties.HorizontalAlignment.CENTER;//頭部的對其方式,預設為居中
        float headerFontSize = 9f;//頭部字體大小
        float rowFontSize = 9f;//行記錄字體大小
        float? headerFixHeight = null;//頭部的固定高度,否則為自適應

        var success = TextSharpHelper.ExportTableToPdf(title, table, pdfFile, isLandscape, includeHeader, headerAlignment, headerFontSize, rowFontSize, headerFixHeight);

        //提示信息
        var message = success ? "導出操作成功" : "導出操作失敗";
        if (success)
        {
            Growl.SuccessGlobal(message);
            Process.Start("explorer.exe", pdfFile);
        }
        else
        {
            Growl.ErrorGlobal(message);
        }
    }
}

通過把List<T>的列表轉換為常規的DataTable來處理,我們就可以利用之前我們隨筆《在Winform分頁控制項中集成導出PDF文檔的功能》介紹到的PDF導出函數來實現WPF數據導出到PDF的處理。

上面的 TextSharpHelper 就是對於itext7進行的封裝,實現PDF的導出處理。

 引入相關的Nugget類後,封裝它的輔助類代碼如下所示。

    /// <summary>
    /// 基於iText7對PDF的導出處理
    /// </summary>
    public static class TextSharpHelper
    {
        /// <summary>
        /// datatable轉PDF方法
        /// </summary>
        /// <param name="title">標題內容</param>
        /// <param name="data">dataTable數據</param>
        /// <param name="pdfFile">PDF文件保存的路徑</param>
        /// <param name="isLandscape">是否為橫向列印,預設為true</param>
        /// <param name="includeHeader">是否每頁包含表頭信息</param>
        /// <param name="headerAlignment">頭部的對其方式,預設為居中對其</param>
        /// <param name="headerFontSize">頭部字體大小</param>
        /// <param name="rowFontSize">行記錄字體大小</param>
        /// <param name="headerFixHeight">頭部的固定高度,否則為自適應</param>
        /// <returns></returns>
        public static bool ExportTableToPdf(string title, DataTable data, string pdfFile, bool isLandscape = true, bool includeHeader = true, iText.Layout.Properties.HorizontalAlignment headerAlignment = iText.Layout.Properties.HorizontalAlignment.CENTER, float headerFontSize = 9f, float rowFontSize = 9f, float? headerFixHeight = null)
        {var writer = new PdfWriter(pdfFile);
            PdfDocument pdf = new PdfDocument(writer);
            pdf.SetDefaultPageSize(isLandscape ? PageSize.A4.Rotate() : PageSize.A4); //A4橫向
            var doc = new Document(pdf);//設置標題
            if (!string.IsNullOrEmpty(title))
            {
                var param = new Paragraph(title)
                         .SetFontColor(iText.Kernel.Colors.ColorConstants.BLACK)
                         .SetBold()  //粗體
                         .SetFontSize(headerFontSize + 5)
                         .SetTextAlignment(TextAlignment.CENTER); //居中
                doc.Add(param);
            }
            var table = new Table(data.Columns.Count)
                .SetTextAlignment(TextAlignment.CENTER)
                .SetVerticalAlignment(VerticalAlignment.MIDDLE)
                .SetWidth(new UnitValue(UnitValue.PERCENT, 100));//縮放比例
            table.UseAllAvailableWidth();
            //添加表頭
            foreach (DataColumn dc in data.Columns)
            {
                var caption = !string.IsNullOrEmpty(dc.Caption) ? dc.Caption : dc.ColumnName;
                var cell = new Cell().Add(new Paragraph(caption))
                    .SetBold()
                    .SetVerticalAlignment(VerticalAlignment.MIDDLE)
                    .SetHorizontalAlignment(headerAlignment)
                    .SetPadding(1)
                    .SetFontSize(headerFontSize);
                if (headerFixHeight.HasValue)
                {
                    cell.SetHeight(new UnitValue(UnitValue.POINT, headerFixHeight.Value));
                }
                table.AddHeaderCell(cell);
            }
            //插入數據
            var colorWhite = Color.ConvertRgbToCmyk(iText.Kernel.Colors.WebColors.GetRGBColor("White"));// System.Drawing.Color.White;
            var colorEvent = iText.Kernel.Colors.WebColors.GetRGBColor("LightCyan");// System.Drawing.Color.LightCyan;
            var EventRowBackColor = Color.ConvertRgbToCmyk(colorEvent);
            for (int i = 0; i < data.Rows.Count; i++)
            {
                table.StartNewRow();//第一列開啟新行
                var backgroudColor = ((i % 2 == 0) ? colorWhite : EventRowBackColor);
                for (int j = 0; j < data.Columns.Count; j++)
                {
                    var text = data.Rows[i][j].ToString();
                    var cell = new Cell()
                        .SetBackgroundColor(backgroudColor)
                        .SetFontSize(rowFontSize)
                        .SetVerticalAlignment(VerticalAlignment.MIDDLE)
                        .Add(new Paragraph(text));
                    table.AddCell(cell);
                }
            }
            doc.Add(table);
            pdf.Close();
            writer.Close();
            return true;
        }
    }

導出PDF的文檔效果如下所示。

 

4、導入Excel數據

 Excel數據的導入,可以降低批量處理數據的難度和繁瑣的界面一個個錄入,這種是一種常見的操作方式,我們主要提供固定的模板給客戶下載錄入數據,然後提交進行批量的導入即可。

導入的界面處理,我們這裡涉及一個通用的導入界面(和WInform端的界面類似),這樣我們每個不同的業務導入處理都可以重用,只需要設置一些不同的屬性,以及一些事件的處理即可,如下是通用的界面效果。

 我們這裡主要針對性的介紹它的設計方式,前面我們介紹,在業務界面裡面調用它的時候,如下代碼所示。

/// <summary>
/// 導出內容到Excel
/// </summary>
[RelayCommand]
private void ImportExcel()
{
    var page = App.GetService<ImportExcelData>();
    page!.ViewModel.Items?.Clear();
    page!.ViewModel.TemplateFile = $"系統用戶信息-模板.xls";
    page!.OnDataSave -= ExcelData_OnDataSave;
    page!.OnDataSave += ExcelData_OnDataSave;

    //導航到指定頁面
    ViewModel.Navigate(typeof(ImportExcelData));
}

這個通用的窗體裡面的視圖模型,定義了一個模板的文件名稱,以及一個通用的數據DataTable的集合,以及一個事件用於子類的導入轉換的實現,它的視圖模型類代碼如下所示。

    /// <summary>
    /// 批量導入Excel數據的視圖模型基類
    /// </summary>
    public partial class ImportExcelDataViewModel : BaseViewModel
    {
        [ObservableProperty]
        private string templateFile;

        [ObservableProperty]
        private string importFilePath;

        [ObservableProperty]
        private DataTable items;

我們為了給客戶打開模板文件,方便用於錄入Excel數據,因此我們在本地打開模板文件即可。

        /// <summary>
        /// 打開模板文件
        /// </summary>
        [RelayCommand]
        private void OpenFile()
        {
            if (!this.TemplateFile.IsNullOrEmpty())
            {
                var realFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, this.TemplateFile);
                if (File.Exists(realFilePath))
                {
                    Process.Start("explorer.exe", realFilePath);
                }
                else
                {
                    MessageDxUtil.ShowError($"沒有找到該模板文件:{realFilePath}");
                }
            }
        }

在通用的導入頁面的後臺代碼裡面,我們需要實現一些如選擇Excel後,顯示數據到DataGrid的操作,以及批量保存數據的處理。

        /// <summary>
        /// 選擇Excel文件後,顯示Excel裡面的表格數據
        /// </summary>
        [RelayCommand]
        private void BrowseExcel()
        {
            string file = FileDialogHelper.OpenExcel();
            if (!string.IsNullOrEmpty(file))
            {
                this.ViewModel.ImportFilePath = file;
                ViewData();
            }
        }    
        /// <summary>
        /// 查看Excel文件並顯示在界面上操作
        /// </summary>
        private void ViewData()
        {
            if (this.txtFilePath.Text == "")
            {
                MessageDxUtil.ShowTips("請選擇指定的Excel文件");
                return;
            }

            try
            {
                var myDs = new DataSet();

                string error = "";
                AsposeExcelTools.ExcelFileToDataSet(this.txtFilePath.Text, out myDs, out error);
                this.ViewModel.Items = myDs.Tables[0];
            }
            catch (Exception ex)
            {
                LogTextHelper.Error(ex);
                MessageDxUtil.ShowError(ex.Message);
            }
        }

導入處理的操作代碼如下所示。

/// <summary>
/// 批量保存數據到資料庫
/// </summary>
/// <returns></returns>
[RelayCommand]
private async Task<CommonResult> SaveData()
{            
    if (ViewModel.Items == null || ViewModel.Items?.Rows?.Count == 0)
        return new CommonResult(false);

    if (MessageDxUtil.ShowYesNoAndWarning("該操作將把數據導入到系統資料庫中,您確定是否繼續?") ==  System.Windows.MessageBoxResult.Yes)
    {
        var dt = this.ViewModel.Items;
        foreach (DataRow dr in dt.Rows)
        {
            try
            {
                await OnDataSave(dr);
            }
            catch (Exception ex)
            {
                LogTextHelper.Error(ex);
                MessageDxUtil.ShowError(ex.Message);
            }
        }
        return new CommonResult(true, "操作成功");
    }
    return new CommonResult(false);
}

註意,我們這裡使用了事件的處理,把數據的轉換邏輯留給子類去實現的。

        /// <summary>
        /// 數據保存的事件
        /// </summary>
        public event SaveDataHandler OnDataSave;

這樣我們在用戶信息的導入頁面UserListPage.xaml.cs裡面的代碼就可以根據實際的情況進行實現事件了。

    /// <summary>
    /// 導出內容到Excel
    /// </summary>
    [RelayCommand]
    private void ImportExcel()
    {
        var page = App.GetService<ImportExcelData>();
        page!.ViewModel.Items?.Clear();
        page!.ViewModel.TemplateFile = $"系統用戶信息-模板.xls";
        page!.OnDataSave -= ExcelData_OnDataSave;
        page!.OnDataSave += ExcelData_OnDataSave;

        //導航到指定頁面
        ViewModel.Navigate(typeof(ImportExcelData));
    }

這個事件的實現,主要就是把個性化的用戶信息(用戶信息模板裡面定義的欄位),轉換為DataTable的行信息即可,如下代碼所示。具體根據模板設計的情況進行修改即可。

具體就不再一一贅述,主要就是基類邏輯和具體實現分離,實現不同的業務功能處理即可。

以上即是我們一個列表通用頁面裡面,往往需要用到的通用性的導入、導出操作的介紹,希望對讀者在開發WPF應用功能上有所啟發,有所參考,善莫大焉。

專註於代碼生成工具、.Net/.NetCore 框架架構及軟體開發,以及各種Vue.js的前端技術應用。著有Winform開發框架/混合式開發框架、微信開發框架、Bootstrap開發框架、ABP開發框架、SqlSugar開發框架等框架產品。
  轉載請註明出處:撰寫人:伍華聰  http://www.iqidi.com 
    

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • JDK21 計劃23年9月19日正式發佈,雖然一直以來都是“版本隨便出,換 8 算我輸”,但這麼多年這麼多版本的折騰,如果說之前的 LTS版本JDK17你還覺得不香,那 JDK21還是有必要關註一下,因為會有一批重要更新發佈到生產環境中,特別是千呼萬喚的虛擬線程,雖然說這東西我感覺不需要的用不到,需 ...
  • 前言 MongoDB是一個基於分散式文件存儲的開源資料庫系統,使用C++語言編寫。它是一個介於關係資料庫和非關係資料庫之間的產品,具有類似關係資料庫的功能,但又有一些非關係資料庫的特點。MongoDB的數據模型比較鬆散,採用類似json的bson格式,可以靈活地存儲各種類型的數據 MongoDB的優 ...
  • gRPC 是開發中常用的開源高性能遠程過程調用(RPC)框架,tonic 是基於 HTTP/2 的 gRPC 實現,專註於高性能、互操作性和靈活性。該庫的創建是為了對 async/await 提供一流的支持,並充當用 Rust 編寫的生產系統的核心構建塊。今天我們聊聊通過使用tonic 調用grpc... ...
  • 來源:虛無境的博客 地址:www.cnblogs.com/xuwujing/p/11953697.html 在介紹Nginx的負載均衡實現之前,先簡單的說下負載均衡的分類,主要分為硬體負載均衡和軟體負載均衡,硬體負載均衡是使用專門的軟體和硬體相結合的設備,設備商會提供完整成熟的解決方案,比如F5,在 ...
  • CRC校驗技術是用於檢測數據傳輸或存儲過程中是否出現了錯誤的一種方法,校驗演算法可以通過計算應用與數據的迴圈冗餘校驗(CRC)檢驗值來檢測任何數據損壞。通過運用本校驗技術我們可以實現對特定記憶體區域以及磁碟文件進行完整性檢測,並以此來判定特定程式記憶體是否發生了變化,如果發生變化則拒絕執行,通過此種方法來... ...
  • 近些年來,隨著WPF在生產,製造,工業控制等領域應用越來越廣發,很多企業對WPF開發的需求也逐漸增多,使得很多人看到潛在機會,不斷從Web,WinForm開發轉向了WPF開發,但是WPF開發也有很多新的概念及設計思想,如:數據驅動,數據綁定,依賴屬性,命令,控制項模板,數據模板,MVVM等,與傳統Wi... ...
  • 在我們展示一些參考信息的時候,有所會用樹形列表來展示結構信息,如對於有父子關係的多層級部門機構,以及一些常用如字典大類節點,也都可以利用樹形列表的方式進行展示,本篇隨筆介紹基於WPF的方式,使用TreeView來洗實現結構信息的展示,以及對它的菜單進行的設置、過濾查詢等功能的實現邏輯。 ...
  • 有關mmd播放器,網上也有許多非常漂亮的實現,如 pmxeditor、saba、blender_mmd_tools等等。。 首先我想先介紹下我參考實現的倉庫: sselecirPyM/Coocoo3D: Experimental MMD renderer using DX12 and DXR. (g ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...