我有一个问题问你。我想在运行时在我的数据类中设置一些属性的类别属性。我的数据类是自动生成的,我无法在设计时生成类别。
我在运行时使用以下设置了2个属性的类别,不幸的是,当我为第二个参数设置类别属性时,也再次更改了第一个参数的类别......我错过了什么?
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Reflection;
using System.Diagnostics;
namespace myApplication
{
public partial class Form1 : Form
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.propertyGrid1 = new System.Windows.Forms.PropertyGrid();
this.SuspendLayout();
//
// propertyGrid1
//
this.propertyGrid1.Dock = System.Windows.Forms.DockStyle.Fill;
this.propertyGrid1.Location = new System.Drawing.Point(0, 0);
this.propertyGrid1.Name = "propertyGrid1";
this.propertyGrid1.Size = new System.Drawing.Size(284, 262);
this.propertyGrid1.TabIndex = 0;
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(284, 262);
this.Controls.Add(this.propertyGrid1);
this.Name = "Form1";
this.Text = "Form1";
this.Load += new System.EventHandler(this.Form1_Load);
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.PropertyGrid propertyGrid1;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
Object selectedObject = new Shape()
{
x = 100,
y = 200
};
var x = TypeDescriptor.GetProperties(selectedObject)["x"].Attributes;
CategoryAttribute attrx = (CategoryAttribute)x[typeof(CategoryAttribute)] as CategoryAttribute;
FieldInfo category_x = attrx.GetType().GetField("categoryValue", BindingFlags.NonPublic | BindingFlags.Instance);
if (category_x != null)
{
if (category_x.FieldType == "string".GetType())
{
category_x.SetValue(TypeDescriptor.GetProperties(selectedObject)["x"].Attributes[typeof(CategoryAttribute)], "A_Category_For_x");
}
}
Debug.Assert(attrx.Category == "A_Category_For_x");
var y = TypeDescriptor.GetProperties(selectedObject)["y"].Attributes;
CategoryAttribute attry = (CategoryAttribute)y[typeof(CategoryAttribute)] as CategoryAttribute;
FieldInfo category_y = attry.GetType().GetField("categoryValue", BindingFlags.NonPublic | BindingFlags.Instance);
if (category_y != null)
{
if (category_y.FieldType == "string".GetType())
{
category_y.SetValue(TypeDescriptor.GetProperties(selectedObject)["y"].Attributes[typeof(CategoryAttribute)], "A_Category_For_y");
}
}
Debug.Assert(attrx.Category == "A_Category_For_x"); // here is stops... why is category for x changed????
Debug.Assert(attry.Category == "A_Category_For_y");
propertyGrid1.SelectedObject = selectedObject;
// Force the PropertyGrid to redraw itself
propertyGrid1.Refresh();
}
}
public partial class Shape : System.ComponentModel.INotifyPropertyChanged
{
private short yField;
private short xField;
[System.Xml.Serialization.XmlAttributeAttribute()]
public short y
{
get
{
return this.yField;
}
set
{
if ((this.yField != null))
{
if ((yField.Equals(value) != true))
{
this.yField = value;
this.OnPropertyChanged("y");
}
}
else
{
this.yField = value;
this.OnPropertyChanged("y");
}
}
}
[System.Xml.Serialization.XmlAttributeAttribute()]
public short x
{
get
{
return this.xField;
}
set
{
if ((this.xField != null))
{
if ((xField.Equals(value) != true))
{
this.xField = value;
this.OnPropertyChanged("x");
}
}
else
{
this.xField = value;
this.OnPropertyChanged("x");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
void OnPropertyChanged(string propertyName)
{
System.ComponentModel.PropertyChangedEventHandler handler = this.PropertyChanged;
if ((handler != null))
{
handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
}
}
}
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}
更新/额外信息 我认为 .net 在未明确设置时具有相同的 CategoryAttribute 实例。如果我设置它,我可以像这样更改每个属性的类别:
using System.ComponentModel;
using System.Diagnostics;
using System.Reflection;
using System;
using System.Linq;
namespace CSharpConsoleApplication
{
public static class Program
{
public static void Main()
{
Object selectedObject = new myDataClass
{
x = 100,
y = 200
};
CategoryAttribute attrx =
selectedObject.GetType().GetProperty("x").GetCustomAttributes(typeof(CategoryAttribute), false).Single() as
CategoryAttribute;
FieldInfo category_x = attrx.GetType().GetField("categoryValue", BindingFlags.NonPublic | BindingFlags.Instance);
if (category_x != null)
{
if (category_x.FieldType == "string".GetType())
{
category_x.SetValue(attrx, "categoryX");
}
}
Debug.Assert(attrx.Category == "categoryX");
CategoryAttribute attry =
selectedObject.GetType().GetProperty("y").GetCustomAttributes(typeof(CategoryAttribute), false).Single() as
CategoryAttribute;
FieldInfo category_y = attry.GetType().GetField("categoryValue", BindingFlags.NonPublic | BindingFlags.Instance);
if (category_y != null)
{
if (category_y.FieldType == "string".GetType())
{
category_y.SetValue(attry, "categoryY");
}
}
Debug.Assert(attrx.Category == "categoryX"); //success now!
Debug.Assert(attry.Category == "categoryY");
}
public partial class myDataClass
{
[CategoryAttribute("Test")]
public int x { get; set; }
[CategoryAttribute("Default")]
public int y { get; set; }
}
}
}
如您所见,这是成功的!不幸的是,我的部分类myDataClass是自动生成的,每次生成后我都必须手动设置 CategoryAttribute。我不想这样做,但在运行时设置它......
可能这些额外的信息可以帮助吗?