WinForm小白的WPF初試一:從PropertyGrid控制項,輸出內容到Word(上)

来源:http://www.cnblogs.com/chenyifaer-67373/archive/2016/05/25/5524419.html
-Advertisement-
Play Games

學WinForm也就半年,然後轉到WPF,還在熟悉中。最近拿到一個任務:從PropertyGrid控制項,輸出內容到Word。難點有: 一.PropertyGrid控制項是WinForm控制項,在WPF中並不能直接從工具箱獲得,或者直接在XMAL中聲明使用。 如要使用,需要使用WindowFormHost ...


  學WinForm也就半年,然後轉到WPF,還在熟悉中。最近拿到一個任務:從PropertyGrid控制項,輸出內容到Word。難點有:

一.PropertyGrid控制項是WinForm控制項,在WPF中並不能直接從工具箱獲得,或者直接在XMAL中聲明使用。

  如要使用,需要使用WindowFormHost控制項,再在其內部裝載PropertyGrid控制項。當然前提要在XAML中引用CLR—NAMESAPCE的SYSTEM.WINDOWS.FORMS命名空間。詳細請看此處鏈接:http://www.cnblogs.com/zhuqil/archive/2010/09/02/Wpf-PropertyGrid-Demo.html

 

二.項目中的PropertyGrid控制項通過指定屬性SeletedObject綁定對應的類,從而顯示類中的屬性,不能直接從控制項中獲取控制項內容。

  WPF作為一種聲稱直接操作數據的開發方式,充斥著各式綁定,用戶對UI的操作實際上是對底層數據的操作。如此,我們要獲取屬性內容,就必須要直接從控制項綁定的類中去獲取。在這個項目中,PropertyGrid控制項隨著用戶點擊TreeView上不同的節點,不斷切換指定其SelectedObject屬性綁定節點Item(其實就是綁定節點所綁定的數據類)。

private void trvAllCheckItems_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{
            if (trvAllCheckItems.SelectedItem is ICheckItemGroup || trvAllCheckItems.SelectedItem is ICheckItem)
            {
                m_PropertyGrid.SelectedObject = trvAllCheckItems.SelectedItem;
            }
            else
            {
                TreeViewItem trvi = trvAllCheckItems.SelectedItem as TreeViewItem;
                if (trvi != null)
                {
                    m_PropertyGrid.SelectedObject = trvi.Tag;
                }
            }
}

   不同級別的TreeViewItem,綁定不同的類,在底層代碼中,類對我們是可知的。那麼最簡單的方法是直接m_PropertyGrid.SelectedObject is XX(類)判斷是哪個類,然後再as轉換,根據每個類的屬性去獲取值來輸出。但這樣做無疑是簡單粗暴,雖然可行,但太過死板。作為初級開發人員,我還是想寫一些通用性更高的方法。

  假設,我不知道PropertyGrid控制項綁定的對象是哪種類,其對象是動態的,未知的,那麼如何獲得綁定對象的屬性(Property)值和屬性特性(Attribute)呢?註:某些特定的特性會影響PropertyGrid控制項的顯示效果,如:System.ComponentModel.BrowsableAttribute。詳細請看此處鏈接:http://blog.csdn.net/luyifeiniu/article/details/5426960

  從網上搜了一種方法,使用Type.GetProperties()可以獲取某一類型的屬性信息集合,而遍歷得到每個屬性信息通過PropertyInfo.GetCustomAttributes(true)又可以獲得此屬性的特性。通過這種方法,我們可以得到此對象類型的每個屬性名以及每個屬性上的每個特性信息。那麼如何獲取此時對象的某個屬性的值呢?

  很簡單,通過獲取的ProperInfo.GetValue(object 此對象,null)方法,代碼如下:

            if (m_PropertyGrid == null || m_PropertyGrid.SelectedObject == null)
                return;
            object SelecteObject = m_PropertyGrid.SelectedObject;
            Type t = SelecteObject.GetType();
            DataSet ds = new DataSet();
            string m_SaveCheckSchemaPath = "";

            //有Category特性標記
            bool IsHaveCategory = false;
            //不創建DataTable標記,初始值為創建
            bool IsNotCreateDT = false;

            //遍歷屬性,每種Category特性創建一個DataTable
            foreach (PropertyInfo ProInfo in t.GetProperties())
            {
                System.ComponentModel.BrowsableAttribute m_BrowsableAttribute = null;
                System.ComponentModel.CategoryAttribute m_CategoryAttribute = null;
                System.ComponentModel.DisplayNameAttribute m_DisplayNameAttribute = null;
                
                


                foreach (Attribute a in ProInfo.GetCustomAttributes(true))
                {

                    if (a is System.ComponentModel.BrowsableAttribute)
                        m_BrowsableAttribute = (System.ComponentModel.BrowsableAttribute)a;
                    if (a is System.ComponentModel.CategoryAttribute)
                        m_CategoryAttribute = (System.ComponentModel.CategoryAttribute)a;
                    if (a is System.ComponentModel.DisplayNameAttribute)
                        m_DisplayNameAttribute = (System.ComponentModel.DisplayNameAttribute)a;
                }
                if (m_BrowsableAttribute != null && m_BrowsableAttribute.Browsable == false)
                    continue;//屬性不可見,則跳過此項
                if (m_CategoryAttribute != null)
                {
                    //有Category特性標記
                    IsHaveCategory = true;
                    foreach (DataTable dt in ds.Tables)
                    {
                        if (dt.Columns[0].ColumnName == m_CategoryAttribute.Category)
                        {
                            DataRow row = dt.NewRow();
                            if (m_DisplayNameAttribute == null)
                                row[m_CategoryAttribute.Category] = ProInfo.Name;
                            else
                                row[m_CategoryAttribute.Category] = m_DisplayNameAttribute.DisplayName;
                            row[1] = ProInfo.GetValue(SelecteObject, null);
                            dt.Rows.Add(row);
                            //已存在的類型表,則標記為不創建
                            IsNotCreateDT = true;
                        }
                    }
                    if (IsNotCreateDT)
                    {
                        IsNotCreateDT = false;
                        IsHaveCategory = false;
                        continue;//不創建新表,則跳過後續操作
                    }

                    DataTable DT = new DataTable();
                    DT.Columns.Add(m_CategoryAttribute.Category, typeof(string));
                    DT.Columns.Add("", typeof(string));
                    DataRow Row = DT.NewRow();
                    if (m_DisplayNameAttribute == null)
                        Row[m_CategoryAttribute.Category] = ProInfo.Name;
                    else
                        Row[m_CategoryAttribute.Category] = m_DisplayNameAttribute.DisplayName;
                    Row[1] = ProInfo.GetValue(SelecteObject, null);
                    DT.Rows.Add(Row);
                    ds.Tables.Add(DT);
                       
                }
                
                //如果此屬性沒有CategoryAttribute,則為雜項類型
                if (!IsHaveCategory)
                {
                    foreach (DataTable dt in ds.Tables)
                    {
                        if (dt.Columns[0].ColumnName == "雜項")
                        {
                            DataRow row = dt.NewRow();
                            if (m_DisplayNameAttribute == null)
                                row["雜項"] = ProInfo.Name;
                            else
                                row["雜項"] = m_DisplayNameAttribute.DisplayName;
                            row[1] = ProInfo.GetValue(SelecteObject, null);
                            dt.Rows.Add(row);
                            //已存在的類型表,則標記為不創建
                            IsNotCreateDT = true;
                        }
                    }
                    if (IsNotCreateDT)
                    {
                        IsNotCreateDT = false;
                        continue;//不創建新表,則跳過後續操作
                    }
                    DataTable DT = new DataTable();
                    DT.Columns.Add("雜項", typeof(string));
                    DT.Columns.Add("", typeof(string));
                    DataRow Row = DT.NewRow();
                    if (m_DisplayNameAttribute == null)
                        Row["雜項"] = ProInfo.Name;
                    else
                        Row["雜項"] = m_DisplayNameAttribute.DisplayName;
                    Row[1] = ProInfo.GetValue(SelecteObject, null);
                    DT.Rows.Add(Row);
                    ds.Tables.Add(DT);
                }
                IsHaveCategory = false;
                
            }        
View Code

 

  寫的可能不是很簡潔,嵌套很多,但已經是改良版了,天知道我之前寫得有多麻煩!整個代碼的目的是把未知的綁定類根據其屬性分類,每個類別創建一個DataTable,存入此類的屬性,最後都加到DataSet里。再之後,我們會輸出這個DataSet的每張表到Word中。


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

-Advertisement-
Play Games
更多相關文章
  • 不廢話,直接上如何利用Asp.NET操作XML文件,並對其屬性進行修改,剛開始的時候,是打算使用JS來控制生成XML文件的,但是最後卻是無法創建文件,讀取文件則沒有使用了 index.aspx 文件 index.aspx.cs文件 Command.cs 文件 UserEdit.aspx UserEd ...
  • 1、var 1、均是聲明動態類型的變數。 2、在編譯階段已經確定類型,在初始化的時候必須提供初始化的值。 3、無法作為方法參數類型,也無法作為返回值類型。 2、dynamic 1、均是聲明動態類型的變數。 2、運行時檢查類型,不存在語法類型,在初始化的時候可以不提供初始化的值。 3、反射時簡化代碼, ...
  • 1、通過Nuget下載CORS安裝包 2、在WebApiConfig.cs文件中註冊CORS 3、在全局文件啟用CORS支持 4、在控制器上添加頭 ...
  • 今天ModestMT.Zou發佈了DotnetSpider爬蟲第二章節,內容簡單明瞭,基本看懂了,於是想自己試試看,直接就拿博客園開刀了。 這裡有最基本的使用方式,本文章不介紹 [開源 .NET 跨平臺 數據採集 爬蟲框架: DotnetSpider] [二] 最基本,最自由的使用方式 這裡我已經從 ...
  • 本著簡潔直接,我們就直奔主題吧! 下麵是一個生成數字和字母隨機組合的驗證碼類源代碼: using System; using System.Drawing; using System.Drawing.Imaging; using System.Web.UI; using System.Drawing ...
  • 1. 2.跳轉的另一個頁面 3.Get傳值:跳轉頁面.cs頁面 4. 跳轉頁面前端頁面 效果顯示: ...
  • DataTable dtPCI = dtblSourceData.DefaultView.ToTable(true, new string[] { "Server Cell PCI" }); 根據現有 DataView 中的行,創建並返回一個新的 DataTable。 命名空間:System.Dat ...
  • 第一個NhIbernate程式 1、目的: a) 鏈接到oracle資料庫 b) 增刪改 c) 基本查詢、sql查詢 d) 視圖查詢 e) 使用存儲過程 f) 多表查詢、級聯查詢 g) 級聯增刪改 2、後續目的 a) 載入機制——立即載入or延遲載入 b) 併發控制 c) 緩存——一級緩存,二級緩存 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...