学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[].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[] = 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[] = ProInfo.GetValue(SelecteObject, null);
DT.Rows.Add(Row);
ds.Tables.Add(DT); } //如果此属性没有CategoryAttribute,则为杂项类型
if (!IsHaveCategory)
{
foreach (DataTable dt in ds.Tables)
{
if (dt.Columns[].ColumnName == "杂项")
{
DataRow row = dt.NewRow();
if (m_DisplayNameAttribute == null)
row["杂项"] = ProInfo.Name;
else
row["杂项"] = m_DisplayNameAttribute.DisplayName;
row[] = 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[] = ProInfo.GetValue(SelecteObject, null);
DT.Rows.Add(Row);
ds.Tables.Add(DT);
}
IsHaveCategory = false; }

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

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

  1. WinForm窗体PropertyGrid控件的使用

    使用过 Microsoft Visual Basic 或 Microsoft Visual Studio .NET的朋友,一定使用过属性浏览器来浏览.查看或编辑一个或多个对象的属性..NET 框架 P ...

  2. PropertyGrid控件由浅入深(一):文章大纲

    Winform中PropertyGrid控件是一个非常好用的对象属性编辑工具,对于Key-Value形式的数据的处理也是非常的好用. 因为Property控件设计良好,在很小的空间内可以展示很多的内容 ...

  3. WPF不同线程之间的控件的访问

    原文:WPF不同线程之间的控件的访问 WPF不同线程之间的控件是不同访问的,为了能够访问其他线程之间的控件,需要用Dispatcher.Invoke执行一个新的活动即可. 例如: public voi ...

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

    一.控件到底是什么 控件的本质是“数据+算法”——用户输入原始数据,算法处理原始数据并得到结果数据.问题就在于程序如何将结果数据展示给用户.同样一组数据,你可以使用LED阵列显示出来,或者是以命令行模 ...

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

    微信公众号:Dotnet9,网站:Dotnet9,问题或建议:请网站留言, 如果对您有所帮助:欢迎赞赏. .NET CORE(C#) WPF 方便的实现用户控件切换(祝大家新年快乐) 快到2020年了 ...

  6. WPF自定义控件第一 - 进度条控件

    本文主要针对WPF新手,高手可以直接忽略,更希望高手们能给出一些更好的实现思路. 前期一个小任务需要实现一个类似含步骤进度条的控件.虽然对于XAML的了解还不是足够深入,还是摸索着做了一个.这篇文章介 ...

  7. PropertyGrid控件由浅入深(二):基础用法

    目录 PropertyGrid控件由浅入深(一):文章大纲 PropertyGrid控件由浅入深(二):基础用法 控件的外观构成 控件的外观构成如下图所示: PropertyGrid控件包含以下几个要 ...

  8. winform快速开发平台 -> 快速绑定ComboBox数据控件

    通常我们在处理编辑窗体时.往往会遇到数据绑定.例如combobox控件绑定数据字典可能是我们经常用到的.然而在我的winform快速开发平台中我是如何处理这个频繁的操作呢? 首先,我们要绑定combo ...

  9. winform快速开发平台 -> 基础组件之分页控件

    一个项目控件主要由及部分的常用组件,当然本次介绍的是通用分页控件. 处理思想:我们在处理分页过程中主要是针对数据库操作. 一般情况主要是传递一些开始位置,当前页数,和数据总页数以及相关关联的业务逻辑. ...

随机推荐

  1. ReactMix框架,让你实现一套js代码,基于ReactNative在H5,App都能完美跑起来,Write Once,Run Anywhere

    ReactNative框架推出已经有一段时间了,相信很多小伙伴都在尝试实现Write Once, Run Anywhere的梦想,比如淘宝的ReactWeb等等,但是这些框架都局限于因为ReactNa ...

  2. C++ static

    本文主要记录的C++中static的一些内容,内容简单,仅仅作为梳理一下知识,如有错误请留言指出. static的作用 在函数体,一个被声明为static的变量,在这一函数被调用的过程里,其数值维持不 ...

  3. SQL——索引

    索引是根据表中一列或若干列按照一定顺序建立的列值与记录行之间的对应关系表.在数据库系统中建立索引主要有以下作用: l快速存取数据: l保证数据记录的唯一性: l实现表与表之间的参照完整性: l在使用O ...

  4. WebApi系列~基于单请求封装多请求的设计~请求的安全性设计与实现

    回到目录 对于一个Http请求如何保证它的安全,这已经不是一个新的话题,对于请求的安全我们通常考虑的无非就是"请求的被篡改性"和"请求的被复制性",第一个问题我们很容易实现,可以通过参数+密钥的方式, ...

  5. Linux之VSFTP服务

    一 .文件服务器简介 ftp:在内网和公网使用. 服务器:windows,linux 客户端:windows,linux samba:只能在内网使用(文件共享服务) 服务器:windows,linux ...

  6. Atitit 基于图片图像 与文档混合文件夹的分类

    Atitit 基于图片图像 与文档混合文件夹的分类 太小的文档(txt doc csv exl ppt pptx)单独分类 Mov10KminiDoc 但是可能会有一些书法图片迁移,因为他们很微小,需 ...

  7. Atitit 混合叠加俩张图片的处理 图像处理解决方案 javafx blend

    Atitit 混合叠加俩张图片的处理 图像处理解决方案 javafx blend 1.1. Jhlabs 好像有了可以叠加算法,但是没有找到doc1 1.2. 自己算法叠加1 1.3. 使用javaf ...

  8. telnet命令——连接服务器

    Telnet协议是TCP/IP协议族中的一员,是Internet远程登陆服务的标准协议和主要方式.它为用户提供了在本地计算机上完成远程主机工作的能力.在终端使用者的电脑上使用telnet程序,用它连接 ...

  9. app的同源和域的问题

    app的同源和域的问题

  10. JS checkbox 全选 全不选

    /* JS checkbox 全选 全不选 Html中checkbox: <input type="checkbox" name="cbx" value= ...