teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

1

見直しキャンペーン中

2023/07/28 16:25

投稿

TN8001
TN8001

スコア10104

answer CHANGED
@@ -1,229 +1,229 @@
1
- 参考URLが誤記とはどういうことでしょうか?
2
-
3
- それに(あえてurlはだしませんが)こういった怪しげな翻訳サイト(最近日本語のも多く見ますね)ではなく元ネタを探しましょう(ほぼ Stack Overflow が元ネタ)
4
- [c# - How to display a dynamic object in property grid? - Stack Overflow](https://stackoverflow.com/questions/3491556/how-to-display-a-dynamic-object-in-property-grid)
5
-
6
- その回答の中で、
7
- > a custom TypeConverter, or (alternatively) ICustomTypeDescriptor/TypeDescriptionProvider.
8
-
9
- とありましたので [ICustomTypeDescriptor](https://docs.microsoft.com/ja-jp/dotnet/api/system.componentmodel.icustomtypedescriptor) のほうでやってみたところ動いている気がします(あっているかは自信ないです^^;
10
-
11
- 参考
12
- [c# - Dynamic PropertyGrid properties - Stack Overflow](https://stackoverflow.com/questions/10688656/dynamic-propertygrid-properties)
13
- [Customized Display of Collection Data in a PropertyGrid - CodeProject](https://www.codeproject.com/Articles/4448/Customized-display-of-collection-data-in-a-Propert)
14
-
15
- `TypeConverter`でも`ConvertFrom`とかがあればいいのかもしれませんが、`PropertyGrid`を使ったことがないのでぶっちゃけ何もわかってません^^;
16
-
17
- ```xaml
18
- <Window
19
- x:Class="Questions353706.MainWindow"
20
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
21
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
22
- xmlns:local="clr-namespace:Questions353706"
23
- xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
24
- Width="800"
25
- Height="450">
26
- <Window.DataContext>
27
- <local:MainWindowViewModel />
28
- </Window.DataContext>
29
- <Grid>
30
- <Grid.ColumnDefinitions>
31
- <ColumnDefinition Width="200" MinWidth="100" />
32
- <ColumnDefinition Width="5" />
33
- <ColumnDefinition Width="*" />
34
- </Grid.ColumnDefinitions>
35
-
36
- <DockPanel>
37
- <ListBox
38
- DisplayMemberPath="Name"
39
- ItemsSource="{Binding CommandList}"
40
- SelectedItem="{Binding CommandProperty.Value}" />
41
- </DockPanel>
42
-
43
- <GridSplitter Grid.Column="1" HorizontalAlignment="Stretch" />
44
-
45
- <DockPanel Grid.Column="2">
46
- <Button
47
- Command="{Binding TestCommand}"
48
- Content="Test"
49
- DockPanel.Dock="Bottom" />
50
- <xctk:PropertyGrid
51
- SelectedObject="{Binding CommandProperty.Value, UpdateSourceTrigger=PropertyChanged}"
52
- ShowSearchBox="False"
53
- ShowSortOptions="False" />
54
- </DockPanel>
55
- </Grid>
56
- </Window>
57
- ```
58
-
59
- ```C#
60
- using Reactive.Bindings;
61
- using System;
62
- using System.Collections.Generic;
63
- using System.Collections.ObjectModel;
64
- using System.ComponentModel;
65
- using System.Diagnostics;
66
- using System.Linq;
67
- using System.Reactive.Linq;
68
- using System.Windows;
69
-
70
- namespace Questions353706
71
- {
72
- public class CustomObjectType : ICustomTypeDescriptor
73
- {
74
- public string Name { get; set; }
75
- public List<CustomProperty> Properties { get; } = new List<CustomProperty>();
76
-
77
- public AttributeCollection GetAttributes() => TypeDescriptor.GetAttributes(this, true);
78
- public string GetClassName() => TypeDescriptor.GetClassName(this, true);
79
- public string GetComponentName() => TypeDescriptor.GetComponentName(this, true);
80
- public TypeConverter GetConverter() => TypeDescriptor.GetConverter(this, true);
81
- public EventDescriptor GetDefaultEvent() => TypeDescriptor.GetDefaultEvent(this, true);
82
- public PropertyDescriptor GetDefaultProperty() => TypeDescriptor.GetDefaultProperty(this, true);
83
- public object GetEditor(Type editorBaseType) => TypeDescriptor.GetEditor(this, editorBaseType, true);
84
- public EventDescriptorCollection GetEvents() => TypeDescriptor.GetEvents(this, true);
85
- public EventDescriptorCollection GetEvents(Attribute[] attributes) => TypeDescriptor.GetEvents(this, attributes, true);
86
- public PropertyDescriptorCollection GetProperties() => GetProperties(null);
87
- public PropertyDescriptorCollection GetProperties(Attribute[] attributes)
88
- => new PropertyDescriptorCollection(Properties.Select(x => new CustomPropertyDescriptor(x, null)).ToArray());
89
- public object GetPropertyOwner(PropertyDescriptor pd) => this;
90
-
91
-
92
- private class CustomPropertyDescriptor : PropertyDescriptor
93
- {
94
- public override Type ComponentType => Property.Value.GetType();
95
- public override bool IsReadOnly => Property.IsReadOnly;
96
- public override Type PropertyType => Property.Value.GetType();
97
-
98
- public override string Name => Property.Name;
99
- public override string Description => Property.Description;
100
- public override string Category => Property.Category;
101
- public override string DisplayName => Property.Name;
102
- public override bool IsBrowsable => Property.IsVisible;
103
-
104
- private readonly CustomProperty Property;
105
-
106
- public CustomPropertyDescriptor(CustomProperty Property, Attribute[] Attributes)
107
- : base(Property.Name, Attributes) => this.Property = Property;
108
-
109
- public override bool CanResetValue(object component) => true;
110
- public override object GetValue(object component) => Property.Value;
111
- public override void ResetValue(object component) { }
112
- public override void SetValue(object component, object value) => Property.Value = value;
113
- public override bool ShouldSerializeValue(object component) => true;
114
- }
115
- }
116
-
117
- public class CustomProperty
118
- {
119
- public string Category { get; set; }
120
- public string Name { get; set; }
121
- public object Value { get; set; }
122
- public string Description { get; set; }
123
- public bool IsReadOnly { get; set; }
124
- public bool IsVisible { get; set; } = true;
125
- public Type Type { get; set; }
126
- }
127
-
128
- public class CommandInfo
129
- {
130
- public string CommandName { get; set; }
131
- public string Summery { get; set; }
132
- public string Detail { get; set; }
133
- public int RequestParamNum { get; set; }
134
- public int ResponseParamNum { get; set; }
135
- }
136
-
137
- public class MainWindowViewModel
138
- {
139
- public ReactiveProperty<CustomObjectType> CommandProperty { get; } = new ReactiveProperty<CustomObjectType>();
140
- public ObservableCollection<CustomObjectType> CommandList { get; }
141
- public ReactiveCommand TestCommand { get; }
142
-
143
- public MainWindowViewModel()
144
- {
145
- CommandList = new ObservableCollection<CustomObjectType>(
146
- Enumerable.Range(1, 5).Select(x => GetCommandProperty(new CommandInfo
147
- {
148
- CommandName = $"CommandName{x}",
149
- Summery = $"Summery{x}",
150
- Detail = $"Detail{x}",
151
- RequestParamNum = x,
152
- ResponseParamNum = x,
153
- })));
154
-
155
- TestCommand = new ReactiveCommand().WithSubscribe(() =>
156
- {
157
- if (CommandProperty.Value == null) return;
158
- Debug.WriteLine($"\n{CommandProperty.Value.Name}");
159
- foreach (var property in CommandProperty.Value.Properties)
160
- Debug.WriteLine($"{property.Name}: {property.Value}");
161
- });
162
- }
163
-
164
- private CustomObjectType GetCommandProperty(CommandInfo info)
165
- {
166
- var description = $"{info.Summery}\n{info.Detail}";
167
- var result = new CustomObjectType
168
- {
169
- Name = $"{info.CommandName}",
170
- };
171
- result.Properties.Add(new CustomProperty
172
- {
173
- Category = "CommandInformation",
174
- Name = "CommandName",
175
- Type = typeof(string),
176
- Description = description,
177
- Value = info.CommandName,
178
- });
179
- result.Properties.Add(new CustomProperty
180
- {
181
- Category = "CommandInformation",
182
- Name = "AdjustBlock",
183
- Type = typeof(string),
184
- Description = description,
185
- Value = info.CommandName,
186
- });
187
- result.Properties.Add(new CustomProperty
188
- {
189
- Category = "CommandInformation",
190
- Name = "AdjustCode",
191
- Type = typeof(string),
192
- Description = description,
193
- Value = info.CommandName,
194
- });
195
-
196
- for (var i = 0; i < info.RequestParamNum; i++)
197
- {
198
- result.Properties.Add(new CustomProperty
199
- {
200
- Category = "RequestParameter",
201
- Name = $"S{i}",
202
- Type = typeof(uint),
203
- Description = $"S{i}",
204
- Value = 0,
205
- });
206
- }
207
-
208
- for (var i = 0; i < info.ResponseParamNum; i++)
209
- {
210
- result.Properties.Add(new CustomProperty
211
- {
212
- Category = "ResponseParameter",
213
- Name = $"R{i}",
214
- Type = typeof(uint),
215
- Description = $"R{i}",
216
- Value = 0,
217
- });
218
- }
219
-
220
- return result;
221
- }
222
- }
223
-
224
- public partial class MainWindow : Window
225
- {
226
- public MainWindow() => InitializeComponent();
227
- }
228
- }
1
+ 参考URLが誤記とはどういうことでしょうか?
2
+
3
+ それに(あえてurlはだしませんが)こういった怪しげな翻訳サイト(最近日本語のも多く見ますね)ではなく元ネタを探しましょう(ほぼ Stack Overflow が元ネタ)
4
+ [c# - How to display a dynamic object in property grid? - Stack Overflow](https://stackoverflow.com/questions/3491556/how-to-display-a-dynamic-object-in-property-grid)
5
+
6
+ その回答の中で、
7
+ > a custom TypeConverter, or (alternatively) ICustomTypeDescriptor/TypeDescriptionProvider.
8
+
9
+ とありましたので [ICustomTypeDescriptor](https://docs.microsoft.com/ja-jp/dotnet/api/system.componentmodel.icustomtypedescriptor) のほうでやってみたところ動いている気がします(あっているかは自信ないです^^;
10
+
11
+ 参考
12
+ [c# - Dynamic PropertyGrid properties - Stack Overflow](https://stackoverflow.com/questions/10688656/dynamic-propertygrid-properties)
13
+ [Customized Display of Collection Data in a PropertyGrid - CodeProject](https://www.codeproject.com/Articles/4448/Customized-display-of-collection-data-in-a-Propert)
14
+
15
+ `TypeConverter`でも`ConvertFrom`とかがあればいいのかもしれませんが、`PropertyGrid`を使ったことがないのでぶっちゃけ何もわかってません^^;
16
+
17
+ ```xml
18
+ <Window
19
+ x:Class="Questions353706.MainWindow"
20
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
21
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
22
+ xmlns:local="clr-namespace:Questions353706"
23
+ xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
24
+ Width="800"
25
+ Height="450">
26
+ <Window.DataContext>
27
+ <local:MainWindowViewModel />
28
+ </Window.DataContext>
29
+ <Grid>
30
+ <Grid.ColumnDefinitions>
31
+ <ColumnDefinition Width="200" MinWidth="100" />
32
+ <ColumnDefinition Width="5" />
33
+ <ColumnDefinition Width="*" />
34
+ </Grid.ColumnDefinitions>
35
+
36
+ <DockPanel>
37
+ <ListBox
38
+ DisplayMemberPath="Name"
39
+ ItemsSource="{Binding CommandList}"
40
+ SelectedItem="{Binding CommandProperty.Value}" />
41
+ </DockPanel>
42
+
43
+ <GridSplitter Grid.Column="1" HorizontalAlignment="Stretch" />
44
+
45
+ <DockPanel Grid.Column="2">
46
+ <Button
47
+ Command="{Binding TestCommand}"
48
+ Content="Test"
49
+ DockPanel.Dock="Bottom" />
50
+ <xctk:PropertyGrid
51
+ SelectedObject="{Binding CommandProperty.Value, UpdateSourceTrigger=PropertyChanged}"
52
+ ShowSearchBox="False"
53
+ ShowSortOptions="False" />
54
+ </DockPanel>
55
+ </Grid>
56
+ </Window>
57
+ ```
58
+
59
+ ```cs
60
+ using Reactive.Bindings;
61
+ using System;
62
+ using System.Collections.Generic;
63
+ using System.Collections.ObjectModel;
64
+ using System.ComponentModel;
65
+ using System.Diagnostics;
66
+ using System.Linq;
67
+ using System.Reactive.Linq;
68
+ using System.Windows;
69
+
70
+ namespace Questions353706
71
+ {
72
+ public class CustomObjectType : ICustomTypeDescriptor
73
+ {
74
+ public string Name { get; set; }
75
+ public List<CustomProperty> Properties { get; } = new List<CustomProperty>();
76
+
77
+ public AttributeCollection GetAttributes() => TypeDescriptor.GetAttributes(this, true);
78
+ public string GetClassName() => TypeDescriptor.GetClassName(this, true);
79
+ public string GetComponentName() => TypeDescriptor.GetComponentName(this, true);
80
+ public TypeConverter GetConverter() => TypeDescriptor.GetConverter(this, true);
81
+ public EventDescriptor GetDefaultEvent() => TypeDescriptor.GetDefaultEvent(this, true);
82
+ public PropertyDescriptor GetDefaultProperty() => TypeDescriptor.GetDefaultProperty(this, true);
83
+ public object GetEditor(Type editorBaseType) => TypeDescriptor.GetEditor(this, editorBaseType, true);
84
+ public EventDescriptorCollection GetEvents() => TypeDescriptor.GetEvents(this, true);
85
+ public EventDescriptorCollection GetEvents(Attribute[] attributes) => TypeDescriptor.GetEvents(this, attributes, true);
86
+ public PropertyDescriptorCollection GetProperties() => GetProperties(null);
87
+ public PropertyDescriptorCollection GetProperties(Attribute[] attributes)
88
+ => new PropertyDescriptorCollection(Properties.Select(x => new CustomPropertyDescriptor(x, null)).ToArray());
89
+ public object GetPropertyOwner(PropertyDescriptor pd) => this;
90
+
91
+
92
+ private class CustomPropertyDescriptor : PropertyDescriptor
93
+ {
94
+ public override Type ComponentType => Property.Value.GetType();
95
+ public override bool IsReadOnly => Property.IsReadOnly;
96
+ public override Type PropertyType => Property.Value.GetType();
97
+
98
+ public override string Name => Property.Name;
99
+ public override string Description => Property.Description;
100
+ public override string Category => Property.Category;
101
+ public override string DisplayName => Property.Name;
102
+ public override bool IsBrowsable => Property.IsVisible;
103
+
104
+ private readonly CustomProperty Property;
105
+
106
+ public CustomPropertyDescriptor(CustomProperty Property, Attribute[] Attributes)
107
+ : base(Property.Name, Attributes) => this.Property = Property;
108
+
109
+ public override bool CanResetValue(object component) => true;
110
+ public override object GetValue(object component) => Property.Value;
111
+ public override void ResetValue(object component) { }
112
+ public override void SetValue(object component, object value) => Property.Value = value;
113
+ public override bool ShouldSerializeValue(object component) => true;
114
+ }
115
+ }
116
+
117
+ public class CustomProperty
118
+ {
119
+ public string Category { get; set; }
120
+ public string Name { get; set; }
121
+ public object Value { get; set; }
122
+ public string Description { get; set; }
123
+ public bool IsReadOnly { get; set; }
124
+ public bool IsVisible { get; set; } = true;
125
+ public Type Type { get; set; }
126
+ }
127
+
128
+ public class CommandInfo
129
+ {
130
+ public string CommandName { get; set; }
131
+ public string Summery { get; set; }
132
+ public string Detail { get; set; }
133
+ public int RequestParamNum { get; set; }
134
+ public int ResponseParamNum { get; set; }
135
+ }
136
+
137
+ public class MainWindowViewModel
138
+ {
139
+ public ReactiveProperty<CustomObjectType> CommandProperty { get; } = new ReactiveProperty<CustomObjectType>();
140
+ public ObservableCollection<CustomObjectType> CommandList { get; }
141
+ public ReactiveCommand TestCommand { get; }
142
+
143
+ public MainWindowViewModel()
144
+ {
145
+ CommandList = new ObservableCollection<CustomObjectType>(
146
+ Enumerable.Range(1, 5).Select(x => GetCommandProperty(new CommandInfo
147
+ {
148
+ CommandName = $"CommandName{x}",
149
+ Summery = $"Summery{x}",
150
+ Detail = $"Detail{x}",
151
+ RequestParamNum = x,
152
+ ResponseParamNum = x,
153
+ })));
154
+
155
+ TestCommand = new ReactiveCommand().WithSubscribe(() =>
156
+ {
157
+ if (CommandProperty.Value == null) return;
158
+ Debug.WriteLine($"\n{CommandProperty.Value.Name}");
159
+ foreach (var property in CommandProperty.Value.Properties)
160
+ Debug.WriteLine($"{property.Name}: {property.Value}");
161
+ });
162
+ }
163
+
164
+ private CustomObjectType GetCommandProperty(CommandInfo info)
165
+ {
166
+ var description = $"{info.Summery}\n{info.Detail}";
167
+ var result = new CustomObjectType
168
+ {
169
+ Name = $"{info.CommandName}",
170
+ };
171
+ result.Properties.Add(new CustomProperty
172
+ {
173
+ Category = "CommandInformation",
174
+ Name = "CommandName",
175
+ Type = typeof(string),
176
+ Description = description,
177
+ Value = info.CommandName,
178
+ });
179
+ result.Properties.Add(new CustomProperty
180
+ {
181
+ Category = "CommandInformation",
182
+ Name = "AdjustBlock",
183
+ Type = typeof(string),
184
+ Description = description,
185
+ Value = info.CommandName,
186
+ });
187
+ result.Properties.Add(new CustomProperty
188
+ {
189
+ Category = "CommandInformation",
190
+ Name = "AdjustCode",
191
+ Type = typeof(string),
192
+ Description = description,
193
+ Value = info.CommandName,
194
+ });
195
+
196
+ for (var i = 0; i < info.RequestParamNum; i++)
197
+ {
198
+ result.Properties.Add(new CustomProperty
199
+ {
200
+ Category = "RequestParameter",
201
+ Name = $"S{i}",
202
+ Type = typeof(uint),
203
+ Description = $"S{i}",
204
+ Value = 0,
205
+ });
206
+ }
207
+
208
+ for (var i = 0; i < info.ResponseParamNum; i++)
209
+ {
210
+ result.Properties.Add(new CustomProperty
211
+ {
212
+ Category = "ResponseParameter",
213
+ Name = $"R{i}",
214
+ Type = typeof(uint),
215
+ Description = $"R{i}",
216
+ Value = 0,
217
+ });
218
+ }
219
+
220
+ return result;
221
+ }
222
+ }
223
+
224
+ public partial class MainWindow : Window
225
+ {
226
+ public MainWindow() => InitializeComponent();
227
+ }
228
+ }
229
229
  ```