我正在使用PropertyGrid来显示我的对象的属性。但是,我还允许用户创建自己的属性,并为这些自定义属性设置值。可以拥有这些自定义属性的每个对象都有一个Dictionary集合,其中字符串是标识属性的唯一键,Object是基本类型的值(string,bool,int等)。
我创建了一个自定义PropertyDescriptor,其中包含get和set方法,用于检查Dictionary以查找匹配的键,或者分别使用匹配的键创建/覆盖该值。
但是,我还希望让用户能够清除属性,从而完全从字典中删除其条目。我将代码放在我的自定义PropertyDescriptor的ResetValue覆盖方法中,但是我没有看到任何通过PropertyGrid接口来调用它的方法?它似乎不是一个上下文菜单选项或类似的东西。
因此,如果我有一个带有自定义ResetValue方法的自定义PropertyDescriptor,我如何从PropertyGrid中实际唤起该方法?
答案 0 :(得分:3)
我认为最简单的方法是在属性网格中添加一个contextmenu,菜单项为“Reset”,然后像这样处理它的click事件:
private void resetToolStripMenuItem_Click(object sender, EventArgs e)
{
PropertyDescriptor pd = propGrid.SelectedGridItem.PropertyDescriptor;
pd.ResetValue(propGrid.SelectedObject);
}
我认为Visual Studio会做这样的事情。
答案 1 :(得分:2)
译注: PropertyGrid.SelectedObject在Childobjects中返回错误的Value(组件)。 因此,方法CanResetValue回收了一个不正确的组件。
我的解决方案:
private void OnContextMenuOpening(object sender, CancelEventArgs e)
{
var lGrid = mCurrentControl as PropertyGrid;
if (lGrid != null)
{
var lItem = lGrid.SelectedGridItem;
// Für untergeordnete Eigenschaften kann nicht SelectedObject verwendet werden
// Component ist eine interne Eigenschaft der Klasse System.Windows.Forms.PropertyGridInternal.GridEntry
// ((System.Windows.Forms.PropertyGridInternal.GridEntry)(lItem)).Component
// Zugriff via Reflection
var lComponent = lItem.GetType().GetProperty("Component").GetValue(lItem, null);
if (lComponent != null)
tsmi_Reset.Enabled = lItem.PropertyDescriptor.CanResetValue(lComponent);
else
tsmi_Reset.Enabled = lItem.PropertyDescriptor.CanResetValue(lGrid.SelectedObject);
}
}
// Contextmenu -> Reset
private void OnResetProperty(object sender, EventArgs e)
{
var lGrid = mCurrentControl as PropertyGrid;
if (lGrid != null)
lGrid.ResetSelectedProperty();
}
答案 2 :(得分:0)
对于子对象,对包含属性的对象的引用隐藏在Instance
类的非公共后代的GridItem
属性中。值得庆幸的是,这个属性是这些后代类实现的ITypeDescriptorContext
接口的成员。因此,有一个解决方案包括在所有属性的上下文菜单中正确启用Reset命令:
private void contextMenuToolStrip_Opening(object sender, CancelEventArgs e)
{
var item = propertyGrid.SelectedGridItem;
resetToolStripMenuItem.Enabled = item != null &&
item.GridItemType == GridItemType.Property &&
item is ITypeDescriptorContext context &&
item.PropertyDescriptor.CanResetValue(context.Instance);
}
private void resetToolStripMenuItem_Click(object sender, EventArgs e)
{
propertyGrid.ResetSelectedProperty();
}
答案 3 :(得分:0)
这是我用来重置我的属性
server {
listen 80;
return 301 https://$host$request_uri;
include "/opt/bitnami/nginx/conf/bitnami/*.conf";
location /page/ {
rewrite id/(.*)$ /home/page/index.php?id=$1 last;
}
location /status {
stub_status on;
access_log off;
allow 127.0.0.1;
deny all;
}
}
server {
listen 443 ssl;
location /page/ {
rewrite id/(.*)$ /home/page/index.php?id=$1 last;
}
}
这就是我使用它的方式:
public static void InitResetContextMenuStrip(this PropertyGrid grid, params string[] resettableProperties)
{
if (grid.ContextMenuStrip != null)
return;
var menuStrip = new ContextMenuStrip();
var resetItem = new ToolStripMenuItem("Reset");
resetItem.Click += (s, e) =>
{
try
{
if (resettableProperties.Any(p => grid.SelectedGridItem.PropertyDescriptor.Name == p))
{
grid.SelectedGridItem.PropertyDescriptor.SetValue(grid.SelectedObject, null);
grid.Refresh(); //redraw the grid to reflect the changes
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
};
menuStrip.Items.Add(resetItem);
menuStrip.Opening += (s, e) =>
{
try
{
resetItem.Enabled = resettableProperties.Any(p => grid.SelectedGridItem.PropertyDescriptor.Name == p);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
};
grid.ContextMenuStrip = menuStrip;
}