学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. 据说每个大牛、小牛都应该有自己的库——Ajax

    蹉跎到今天终于要写Ajax部分了,平时工作中除了选择器我用jQuery的最多的就是ajax,所以这部分在自己的框架中必不可少. XMLHttpRequest 我以为对每个使用过Ajax的人来说XMLH ...

  2. spring源码分析(一)IoC、DI

    创建日期:2016.08.06 修改日期:2016.08.07 - 2016.08.12 交流QQ:992591601 参考书籍:<spring源码深度解析>.<spring技术内幕 ...

  3. 【团队分享之二】IT团队绩效提升的一些见解

  4. PHP 函数基础

    1.简单函数     函数四要素:返回类型,函数名,参数列表,函数体 function Show(){      echo "hello";}Show();         输出了 ...

  5. asp.net Web.config 在不同版本的IIS配置的IHttpHandler的访问路径,以及经典模式和集成模式不同的配置

    如果IIS7.0使用.net4.0以上版本的框架,<system.web>中的httpHandlers节点就没有用了,而应该使用微软专为.net4.0以上版本设计的新节点<syste ...

  6. sql语句中获取datetime的日期部分或时间部分

    sql语句中获取datetime的日期部分 sql语句中 经常操作操作datetime类型数据.今天在写一个存储过程的时候需要将 一个datetime的值的 日期部分提取出来.网上有许多这方面的介绍. ...

  7. angular测试-Karma + Jasmine配置

    首先讲一下大致的流程: 需要node环境,首先先要安装node,node不会?请自行搜索.版本>0.8 安装node完成之后先要测试下npm是否测试通过,如下图所示 首先看下目录结构 目录为:F ...

  8. KnockoutJS 3.X API 第四章 数据绑定(2) 控制流foreach绑定

    foreach绑定 foreach绑定主要用于循环展示监控数组属性中的每一个元素,一般用于table标签中 假设你有一个监控属性数组,每当您添加,删除或重新排序数组项时,绑定将有效地更新UI的DOM- ...

  9. Java-集合(没做出来)第四题 (List)写一个函数reverseList,该函数能够接受一个List,然后把该List 倒序排列。 例如: List list = new ArrayList(); list.add(“Hello”); list.add(“World”); list.add(“Learn”); //此时list 为Hello World Learn reverseL

    没做出来 第四题 (List)写一个函数reverseList,该函数能够接受一个List,然后把该List 倒序排列. 例如: List list = new ArrayList(); list.a ...

  10. Pycharm远程调试

    1.在pycharm的安装目录中找到pycharm-debug.egg,将其拷贝到目标主机的/usr/lib/python2.7/dist-packages目录下: 执行: sudo easy_ins ...