WinForm小白的WPF初试一:从PropertyGrid控件,输出内容到Word(上)

  学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;

            }        

  写的可能不是很简洁,嵌套很多,但已经是改良版了,天知道我之前写得有多麻烦!整个代码的目的是把未知的绑定类根据其属性分类,每个类别创建一个DataTable,存入此类的属性,最后都加到DataSet里。再之后,我们会输出这个DataSet的每张表到Word中。

时间: 2024-10-11 14:46:05

WinForm小白的WPF初试一:从PropertyGrid控件,输出内容到Word(上)的相关文章

WinForm窗体PropertyGrid控件的使用

使用过 Microsoft Visual Basic 或 Microsoft Visual Studio .NET的朋友,一定使用过属性浏览器来浏览.查看或编辑一个或多个对象的属性..NET 框架 PropertyGrid 控件是 Visual Studio .NET 属性浏览器的核心.PropertyGrid 控件显示对象或类型的属性,并主要通过使用反射(在运行时提供类型信息的技术)来检索项目的属性.PropertyGrid控件包含以下部分:一般属性.可展开属性.属性类别.属性说明和属性编辑器

《深入浅出WPF》学习总结之控件与布局

一.控件到底是什么 控件的本质是“数据+算法”——用户输入原始数据,算法处理原始数据并得到结果数据.问题就在于程序如何将结果数据展示给用户.同样一组数据,你可以使用LED阵列显示出来,或者是以命令行模式借助各种控制字符(如Tab)对其并输出,但这些都不如图形化用户界面(Graphics User Interface ,GUI)来的友好和方便.GUI是程序界的优胜者,但在Windows上实现图形化界面有很多中方法.每种方法又拥有自己的一套开发理念和工具.每种GUI开发与它的里理念和工具共同组成一种

.NET CORE(C#) WPF 方便的实现用户控件切换(祝大家新年快乐)

微信公众号:Dotnet9,网站:Dotnet9,问题或建议:请网站留言, 如果对您有所帮助:欢迎赞赏. .NET CORE(C#) WPF 方便的实现用户控件切换(祝大家新年快乐) 快到2020年了,祝大家新年快乐,今年2019最后一更,谢谢大家支持! 阅读导航 本文背景 代码实现 本文参考 源码 1. 本文背景 一个系统主界面,放上一个菜单,点击菜单在客户区切换不同的展示界面,这是很常规的设计,见下面展示效果图: 左侧一个菜单,点击菜单,右侧切换界面,界面切换动画使用MD控件的组件实现(自己

【转】PropertyGrid控件中的多级显示

运行效果: 解决方案: MainForm.cs public partial class MainForm : Form { public MainForm() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { CProvincialCapital proCap = new CProvincialCapital("南京市", 10000000); CProvince pro

转载 [WPF][C#]在WPF中内嵌WindowsForm控件-使用WindowsFormsControlLibrary

[WPF][C#]在WPF中内嵌WindowsForm控件-使用WindowsFormsControlLibrary 在[WPF][C#]在WPF中内嵌WindowsForm控件一文中为各位介绍了直接在WPF中使用XAML来嵌入Windows Form控件的作法,不过不是每个人都喜欢写XAML,而且有时候会需要把已经存在的Windows Form应用程序嵌入到WPF中,所以这次就来跟大家介绍怎么使用参考dll档的方式,把dll中的Windows Form加到WPF中. 都说了要使用Windows

NET 框架 PropertyGrid 控件

NET框架PropertyGrid控件是 Visual Studio .NET 属性浏览器的核心.PropertyGrid控件显示对象或类型的属性,并主要通过使用反射来检索项目的属性 首先创建 PropertyGrid 控件要使用 Visual Studio .NET 创建 PropertyGrid 控件,需要将该控件添加到工具箱中,因为默认情况下并不包含该控件.在 Tools(工具)菜单中,选择 Customize Toolbox(自定义工具箱).在对话框中选择 Framework Compo

winform学习日志(二十六)----------控件treeview使用

一:实现功能,获得选中节点,在选中节点下添加节点,折叠,展开,删除,得到选中节点下checked项,选中根节点其下节点也选中,图标.上图 二:相关代码 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windo

C# 如何定义让PropertyGrid控件显示[...]按钮,并且点击后以下拉框形式显示自定义控件编辑属性值

关于PropertyGrid控件的详细用法请参考文献: 1.C# PropertyGrid控件应用心得 2.C#自定义PropertyGrid属性 首先定义一个要在下拉框显示的控件: using System; using System.Windows.Forms; namespace Simon.WinForms.Examples.PropertyGrid { public class EditorControl : UserControl { public EditorControl() {

propertyGrid控件 z

1.如果属性是enum类型,那么自然就是下拉的. 2.如果是你自定义的下拉数据,那么需要用到转换属性标签TypeConverter 参见: http://blog.csdn.net/luyifeiniu/article/details/5426960#创建 PropertyGrid 控件 http://blog.csdn.net/jjhua/article/details/23100143