質問者
PropertyGridの表示名を変更

質問
-
PropertyGridのDisplayNameを変更する方法を探しています.現状,以下のような自作のクラスであればDisplayNameAttributeを充てることで変更できています.
ref class myClass{ private: int myInt; public: myClass(){myInt = 0;}; public: [DisplayName("整数")] property int Int{ int get(){return myInt;} void set(int value){myInt = value;} }; };
しかしVisual C++に既存の,TextBoxクラスやChartクラスのDisplayNameの変更方法が分かりません.ただし,以下のようにしてpropertyを作り直すことで同等の内容の表示名を変更することはできるのですが,すべてのpropertyを書き直すというのはスマートでない気がします.また,この方法ではプロパティ名だけでなくプロパティ値もExpandableObjectConverterなどを用いて定義しなおすことになってしまいます.(そうでなければ教えて頂ければ幸いです)
namespace MyProperty{ ref class MyChart_Size_Converter; [TypeConverter(MyChart_Size_Converter::typeid)] ref class MyChart_Size{ public: System::Drawing::Size size; public: MyChart_Size(int height,int width){ size.Height = height; size.Width = width; } public: [DisplayName("高さ")] [BrowsableAttribute(true)] property int Height{ int get (){return size.Height;}; void set (int value){size.Height = value;}; }; [DisplayName("幅")] [BrowsableAttribute(true)] property int Width{ int get (){return size.Width;}; void set (int value){size.Width = value;}; }; }; ref class MyChart_Size_Converter : public ExpandableObjectConverter{ public: virtual bool CanConvertFrom(ITypeDescriptorContext^ context,Type^ t) override{ if(t == String::typeid){ return true; } return ExpandableObjectConverter::CanConvertFrom(context,t); } public: virtual Object^ ConvertFrom(ITypeDescriptorContext^ context,CultureInfo^ info,Object^ value) override{ if(value->GetType() == String::typeid){ try{ array<String^>^ ss = ((String^)value)->Split(','); MyChart_Size^ outsize = gcnew MyChart_Size(0,0); outsize->size.Height = Int32::Parse(ss[0]); outsize->size.Width = Int32::Parse(ss[1]); return outsize; }catch(...){ } throw gcnew ArgumentException("'整数,整数'で入力して下さい."); } return ExpandableObjectConverter::ConvertFrom(context, info, value); } public: virtual Object^ ConvertTo(ITypeDescriptorContext^ context,CultureInfo^ culture,Object^ value,Type^ destType) override{ if(destType == String::typeid && value->GetType() == MyChart_Size::typeid){ MyChart_Size^ size = (MyChart_Size^)value; return Convert::ToString(size->Height)+","+Convert::ToString(size->Width); } return ExpandableObjectConverter::ConvertTo(context, culture, value, destType); } }; ref class MyChart{ private: System::Windows::Forms::DataVisualization::Charting::Chart^ chart; public: MyChart(System::Windows::Forms::DataVisualization::Charting::Chart^ InputChart){ chart = InputChart; }; public: [Category("レイアウト")] [DisplayName("サイズ")] [BrowsableAttribute(true)] property MyChart_Size^ Size{ MyChart_Size^ get (){return gcnew MyChart_Size(chart->Height,chart->Width);}; void set (MyChart_Size^ value){ chart->Size = value->size; }; }; }; };
もっと簡単に(簡単でなくとも)表示名を変更することはできないでしょうか?
すべての返信
-
C#のサンプルコードでよければ
using System; using System.ComponentModel; using System.Drawing; using System.Windows.Forms; using System.Windows.Forms.Design; using System.Windows.Forms.PropertyGridInternal; namespace WindowsFormsApplication1 { public partial class Form1 : Form { PropertyGrid propertyGrid; public Form1() { InitializeComponent(); propertyGrid = new System.Windows.Forms.PropertyGrid(); propertyGrid.Dock = System.Windows.Forms.DockStyle.Fill; this.Controls.Add(propertyGrid); } protected override void OnShown(EventArgs e) { base.OnShown(e); //表示名変更可能なプロパティタブを作る tab=CustumPropertyGrid.RenamePropertyGridTab.SetAttributeReloadPropertyGridTab(this.propertyGrid); tab.RequestDisplayName += tab_RequestDisplayName; this.propertyGrid.SelectedObject = this; } void tab_RequestDisplayName(object sender, CustumPropertyGrid.RenamePropertyGridTab.DisplayNameEventArgs e) { //適当な表示名 e.DisplayName = "TEST " + e.DisplayName;
System.Diagnostics.Debug.WriteLine(e.PropertyDescriptor.ComponentType.ToString()); } CustumPropertyGrid.RenamePropertyGridTab tab; } } namespace CustumPropertyGrid { /// <summary>プロパティの属性の再読み込みを可能にするPropertyTab</summary> public class RenamePropertyGridTab : PropertyTab { public class DisplayNameEventArgs : EventArgs { public DisplayNameEventArgs(PropertyDescriptor pd) { this.PropertyDescriptor = pd; this.DisplayName = pd.DisplayName; } public string DisplayName { get; set; } public PropertyDescriptor PropertyDescriptor { get; set; } } /// <summary>PropertyTabをPropertyGridに追加してデフォルトのPropertyTabを消します</summary> public static RenamePropertyGridTab SetAttributeReloadPropertyGridTab(PropertyGrid grid) { foreach (PropertyTab tab in grid.PropertyTabs) { if (tab.GetType() == typeof(RenamePropertyGridTab)) { return (RenamePropertyGridTab)tab; } } //AttributeReloadPropertyGridTab; PropertyTab newTab = null; grid.PropertyTabs.AddTabType(typeof(RenamePropertyGridTab), PropertyTabScope.Global); foreach (PropertyTab tab in grid.PropertyTabs) { if (tab.GetType() == typeof(RenamePropertyGridTab)) { newTab = tab; break; } } string propTabName = grid.PropertyTabs[0].TabName; string custumTabName = RenamePropertyGridTab.DefaultTabName; ToolStripItem propButton = null; ToolStripItem custumButton = null; ToolStrip strip = GetToolStrip(grid); if (strip != null) { foreach (ToolStripItem item in strip.Items) { if (item.Text == propTabName) { propButton = item; } else if (item.Text == custumTabName) { custumButton = item; } } } if (propButton != null && custumButton != null) { strip.Items.Remove(propButton); custumButton.Image = propButton.Image; if (custumButton.Image == null) {//速すぎるとイメージが無い custumButton.BackColor = Color.Red; } custumButton.Text = propButton.Text; custumButton.ToolTipText = propButton.ToolTipText; custumButton.PerformClick(); } else { throw new ApplicationException("PropertyGridの構成が変更されているようです"); } return (RenamePropertyGridTab)newTab; } /// <summary>Control内のToolStripを探します</summary> private static ToolStrip GetToolStrip(Control ctl) { ToolStrip strip = ctl as ToolStrip; if (strip == null) { foreach (Control child in ctl.Controls) { strip = GetToolStrip(child); if (strip != null) { break; } } } return strip; } /// <summary>プロパティ名要求イベント</summary> public event EventHandler<DisplayNameEventArgs> RequestDisplayName; private string OnRequestDisplayName(PropertyDescriptor pd) { var rdn = RequestDisplayName; string name = pd.DisplayName; if (rdn != null) { var e = new DisplayNameEventArgs(pd); rdn(this, e); name = e.DisplayName; } return name; } /// <summary></summary><remarks>Bitmapが定義されていないとPropertyGridに表示されないらしい</remarks> public override System.Drawing.Bitmap Bitmap { get {return new System.Drawing.Bitmap(16 , 16);} } /// <summary>元のプロパティタブ</summary> private PropertiesTab defatultTab = new PropertiesTab(); /// <summary>それぞれのプロパティの情報を取得する</summary> public override PropertyDescriptorCollection GetProperties(object component , Attribute[] attributes) { PropertyDescriptorCollection descriptors = new PropertyDescriptorCollection(null , false); PropertyDescriptorCollection defaultDescriptors = defatultTab.GetProperties(component); foreach (PropertyDescriptor descriptor in defaultDescriptors) { // 属性を更新したPropertyDescriptorを作る string name = OnRequestDisplayName(descriptor); descriptors.Add(new RenameDisplayNamePropertyDescripter(descriptor,name)); } return descriptors; } /// <summary>あとで入れ替えるので適当な名前</summary> public override string TabName { get { return DefaultTabName; } } private static string DefaultTabName { get { return "#DumyTabName"; } } /// <summary>属性を更新するためにPropertyDescriptorをラップ</summary> private class RenameDisplayNamePropertyDescripter : PropertyDescriptor { public RenameDisplayNamePropertyDescripter(PropertyDescriptor pd, string displayName) : base(pd) { innerDescriptor = pd; _DisplayName = displayName; } /// <summary>表示名を上書き</summary> public override string DisplayName { get { return _DisplayName; } } private string _DisplayName; #region "PropertyDescriptorのabstract" private PropertyDescriptor innerDescriptor; public override bool CanResetValue(object component) { return innerDescriptor.CanResetValue(component); } public override Type ComponentType { get { return innerDescriptor.ComponentType; } } public override object GetValue(object component) { return innerDescriptor.GetValue(component); } public override bool IsReadOnly { get { return innerDescriptor.IsReadOnly; } } public override Type PropertyType { get { return innerDescriptor.PropertyType; } } public override void ResetValue(object component) { innerDescriptor.ResetValue(component); } public override void SetValue(object component, object value) { innerDescriptor.SetValue(component, value); } public override bool ShouldSerializeValue(object component) { return innerDescriptor.ShouldSerializeValue(component); } #endregion } } }ようはプロパティの情報であるPropertyDescriptorのDisplayNameを変更すれば可能ということです
その他の例:
PropertyGridコントロールで、カテゴリ文字列を自由に変更したい。を
特定のクラスのみでいい場合は、fri32234さんが行っている方法と違いますが、そのクラスにTypeConverterを指定することでProprtyDescriptorを操作できます
#一日分の入力コードが吹っ飛んでへこみ中なのでC++に書き換える気力ないです…orz
オブジェクトのプロパティをPropertyGrid上で展開して設定を行いたい個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)
- 回答の候補に設定 星 睦美 2015年2月24日 2:43