如何使用代码设置PropertyGrid的标签栏宽度
2013-04-18 17:29
225 查看
http://liang.eu/dotnet-development/programmatically-set-column-width-of-the-propertygrid
http://blog.csdn.net/null1/article/details/2037608
Visual Studio里自带的PropertyGrid功能强大,用好了可以省去不少工作。前几天使用到了这个控件,使用过程中发现无法控制控件里标签栏和属性值栏的宽度,Google了一番,发现网上介绍使用这个控件的文章不少,但却没有介绍如何在代码里调整PropertyGrid的标签栏和代码栏的宽度的文章。后来到CodeProject搜索了一下,发现了不少关于PropertyGrid的文章。偶e文不是很好,硬着头皮一篇一篇看了过去,最后功夫不负有心人,总算找到了几篇介绍如何调整标签栏宽度的文章:
Add Custom Properties to a PropertyGrid
.NET PropertyGrid -> How to set column width and description window height(托伟大的GFW的福,这篇文章我是通过TOR才能浏览到)
虽然是不同作者写的,但异曲同工,原理都是通过反射来调用PropertyGrid里自带的的私有成员来实现的。
那么,该如何实现这个功能呢?方法有两种,一种是设置PropertyGrid的labelWidth私有变量;另一种方法是调用PropertyGrid的MoveSplitterTo私有函数。下面详细介绍这两种方法:
第一种:直接设置 labelWidth 私有变量
labelWidth这个私有变量的用途是见名知意,我就不多说了,下面是如何使用反射来设置它的值的方法:
先新建一个类,继承于PropertyGrid,然后重写它的OnLayout方法,代码如下:
[/code]
为什么要有Control propertyGridView = this.Controls[2];这一行代码呢?原来,PropertyGrid控件本身是一个复合控件,它其实是有三个子窗口组成的:PropertyGridToolBar, PropertyGridView和Description Pane。其中子窗口PropertyGridView,也就是this.Controls[2](在VS的代码提示里PropertyGrid控件没有Controls这个属性,说明微软不提倡直接使用此方法,但可以手工直接输入并能正常工作),才是我们平时进行属性设置操作的地方。这里就是先获得PropertyGridView对象的引用,然后再通过反射直接设置它的labelWidth私有变量来实现设置标签栏宽度的。
这个方法有一个小bug:当设置的labelWidth比默认值小的话,鼠标点击PropertyGrid的属性值栏的右边不能选中该属性。如下图的AutoSizeMode属性:
using System.Runtime.InteropServices;
public partial class Form1 : Form
class MyClass
希望对你有帮助。
刘婷
在线技术支持工程师
微软全球技术支持中心
我的测试是按照解答二的方法进行的,但是出现了错误,反馈如下:
首先谢谢你的帮助,但是我按照您的说明进行,启动后一旦PropertyGrid获得焦点,就出现错误,信息为:
未处理的“System.NullReferenceException”类型的异常出现在 system.windows.forms.dll 中。
其他信息: Object reference not set to an instance of an object.
请问是什么原因?
代码如下:
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Runtime.InteropServices;
using System.Text;
namespace WindowsApplication1
微软工程师的解答:
谢谢你的反馈!
我原先是在VS2005中做了测试。现在在VS.NET2003中测试了一下,确实看到了你说的问题。
这个问题的原因对于从unmanaged code到managed code的回调,在回调方法被调用时,送传递的delegate必须是active的,不能正准备垃圾回收。在我们的程序中有两个回调,一个是EnumChildWindows, 另一个是SetWindowLong。对于前者,找到PropertyGridView子窗口的handle以后就不需要再回调了,因此我们可以将所传递的ChildWindowDelegate声明为局部变量;对于后者,只要你在PropertyGrid中有任何操作,对应的回调方法都将被执行,因此所传递的WindowProcDelegate变量必须是全局的。
因此解决的办法是申明一个全局的WindowProcDelegate变量,然后传递给SetWindowLong函数。
public partial class Form1 : Form
{
...
WindowProcDelegate windowProcDelegate;
private void Form1_Load(object sender, EventArgs e)
{
windowProcDelegate = new WindowProcDelegate(WindowProc);
bool result = EnumChildWindows(this.propertyGrid1.Handle, new ChildWindowDelegate(EnumChildProc), "PropertyGridView");
if (result == false)
{
defaultProc = GetWindowLong(expectedChild, GWL_WNDPROC);
SetWindowLong(expectedChild, GWL_WNDPROC, windowProcDelegate);
}
MyClass p = new MyClass();
p.ID = 1;
p.Name = "aa";
this.propertyGrid1.SelectedObject = p;
}
}
希望对你有帮助。
刘婷
在线技术支持工程师
微软全球技术支持中心
=========================================================
至此问题解决。
未完的路:
如果按照解答一的方法进行,我目前没有测试成功,我的思路是找到PropertyGrid中的System.Windows.Forms.PropertyGridInternal.PropertyGridView子控件,然后将其KeyPress事件绑定到一个指定的处理过程上来实现需要的功能。但是我在VS2003中发现PropertyGridView并不是网上说的Controls[2],而是Controls[1],随后我进行了绑定,然而运行却没有效果,不知道为什么?
此外,我也不知道我的方法是否正确?
http://blog.csdn.net/null1/article/details/2037608
Visual Studio里自带的PropertyGrid功能强大,用好了可以省去不少工作。前几天使用到了这个控件,使用过程中发现无法控制控件里标签栏和属性值栏的宽度,Google了一番,发现网上介绍使用这个控件的文章不少,但却没有介绍如何在代码里调整PropertyGrid的标签栏和代码栏的宽度的文章。后来到CodeProject搜索了一下,发现了不少关于PropertyGrid的文章。偶e文不是很好,硬着头皮一篇一篇看了过去,最后功夫不负有心人,总算找到了几篇介绍如何调整标签栏宽度的文章:
Add Custom Properties to a PropertyGrid
.NET PropertyGrid -> How to set column width and description window height(托伟大的GFW的福,这篇文章我是通过TOR才能浏览到)
虽然是不同作者写的,但异曲同工,原理都是通过反射来调用PropertyGrid里自带的的私有成员来实现的。
那么,该如何实现这个功能呢?方法有两种,一种是设置PropertyGrid的labelWidth私有变量;另一种方法是调用PropertyGrid的MoveSplitterTo私有函数。下面详细介绍这两种方法:
第一种:直接设置 labelWidth 私有变量
labelWidth这个私有变量的用途是见名知意,我就不多说了,下面是如何使用反射来设置它的值的方法:
先新建一个类,继承于PropertyGrid,然后重写它的OnLayout方法,代码如下:
using System; using System.Collections.Generic; using System.Text; using System.Windows.Forms; using System.Reflection; namespace TestProject { class PropertyGridEx:PropertyGrid { protected override void OnLayout(LayoutEventArgs e) { int width = 200; Control propertyGridView = this.Controls[2]; Type propertyGridViewType = propertyGridView.GetType(); [code] FieldInfo fldLabelWidth = propertyGridViewType.GetField("labelWidth", BindingFlags.Instance | BindingFlags.NonPublic); fldLabelWidth.SetValue(propertyGridView, width); base.OnLayout(e); } }}
[/code]
为什么要有Control propertyGridView = this.Controls[2];这一行代码呢?原来,PropertyGrid控件本身是一个复合控件,它其实是有三个子窗口组成的:PropertyGridToolBar, PropertyGridView和Description Pane。其中子窗口PropertyGridView,也就是this.Controls[2](在VS的代码提示里PropertyGrid控件没有Controls这个属性,说明微软不提倡直接使用此方法,但可以手工直接输入并能正常工作),才是我们平时进行属性设置操作的地方。这里就是先获得PropertyGridView对象的引用,然后再通过反射直接设置它的labelWidth私有变量来实现设置标签栏宽度的。
这个方法有一个小bug:当设置的labelWidth比默认值小的话,鼠标点击PropertyGrid的属性值栏的右边不能选中该属性。如下图的AutoSizeMode属性:
using System.Runtime.InteropServices;
public partial class Form1 : Form
class MyClass
希望对你有帮助。
刘婷
在线技术支持工程师
微软全球技术支持中心
我的测试是按照解答二的方法进行的,但是出现了错误,反馈如下:
首先谢谢你的帮助,但是我按照您的说明进行,启动后一旦PropertyGrid获得焦点,就出现错误,信息为:
未处理的“System.NullReferenceException”类型的异常出现在 system.windows.forms.dll 中。
其他信息: Object reference not set to an instance of an object.
请问是什么原因?
代码如下:
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Runtime.InteropServices;
using System.Text;
namespace WindowsApplication1
微软工程师的解答:
谢谢你的反馈!
我原先是在VS2005中做了测试。现在在VS.NET2003中测试了一下,确实看到了你说的问题。
这个问题的原因对于从unmanaged code到managed code的回调,在回调方法被调用时,送传递的delegate必须是active的,不能正准备垃圾回收。在我们的程序中有两个回调,一个是EnumChildWindows, 另一个是SetWindowLong。对于前者,找到PropertyGridView子窗口的handle以后就不需要再回调了,因此我们可以将所传递的ChildWindowDelegate声明为局部变量;对于后者,只要你在PropertyGrid中有任何操作,对应的回调方法都将被执行,因此所传递的WindowProcDelegate变量必须是全局的。
因此解决的办法是申明一个全局的WindowProcDelegate变量,然后传递给SetWindowLong函数。
public partial class Form1 : Form
{
...
WindowProcDelegate windowProcDelegate;
private void Form1_Load(object sender, EventArgs e)
{
windowProcDelegate = new WindowProcDelegate(WindowProc);
bool result = EnumChildWindows(this.propertyGrid1.Handle, new ChildWindowDelegate(EnumChildProc), "PropertyGridView");
if (result == false)
{
defaultProc = GetWindowLong(expectedChild, GWL_WNDPROC);
SetWindowLong(expectedChild, GWL_WNDPROC, windowProcDelegate);
}
MyClass p = new MyClass();
p.ID = 1;
p.Name = "aa";
this.propertyGrid1.SelectedObject = p;
}
}
希望对你有帮助。
刘婷
在线技术支持工程师
微软全球技术支持中心
=========================================================
至此问题解决。
未完的路:
如果按照解答一的方法进行,我目前没有测试成功,我的思路是找到PropertyGrid中的System.Windows.Forms.PropertyGridInternal.PropertyGridView子控件,然后将其KeyPress事件绑定到一个指定的处理过程上来实现需要的功能。但是我在VS2003中发现PropertyGridView并不是网上说的Controls[2],而是Controls[1],随后我进行了绑定,然而运行却没有效果,不知道为什么?
此外,我也不知道我的方法是否正确?
相关文章推荐
- 如何使用代码设置PropertyGrid的标签栏宽度
- 如何使用代码动态的获取和设置ImageView的宽度和高度?
- 如何使用代码动态的获取和设置ImageView的宽度和高度?
- 如何使用代码动态的获取和设置ImageView的宽度和高度?
- 转--如何使用代码动态的获取和设置ImageView的宽度和高度?
- a 标签中如何设置其宽度和高度
- CSS中如何把Span标签设置为固定宽度
- CSS 中如何把 Span 标签设置为固定宽度
- html使用display:inline-block实现标签右对齐,值左对齐效果。和设置div宽度,并居中显示。嵌套div的里层div文字居中显示
- 如何用代码设置控制自己网站的网页在360浏览器打开时强制优先使用极速模式,而非兼容模式
- Java 编程下 Eclipse 如何设置单行代码显示的最大宽度
- HTML 的超链接 a 标签中如何设置其宽度和高度?
- 如何使用CSS设置<input>标签的背景小图标 简单
- CSS中如何把Span标签设置为固定宽度
- 使用Libgdx画线,如何设置宽度
- android selector中设置的属性如何在代码中使用
- 在xml布局文件中,我们既可以设置px,也可以设置dp(或者dip)。一般情况下,我们都会选择使用dp,这样可以保证不同屏幕分辨率的机器上布局一致。但是在代码中,如何处理呢?很多控件的方法中都只提供了
- 在storyboard中设置一个一个button,只进行了位置设置,没有使用约束,发现用代码修改不了如何解决
- 【转】如何使用代码动态设置水晶报表中的文本,字段等对象呢?
- Myeclipse、Eclipse 如何设置单行代码显示的最大宽度