回答編集履歴

1

見直しキャンペーン中

2023/07/23 08:13

投稿

TN8001
TN8001

スコア9862

test CHANGED
@@ -1,245 +1,123 @@
1
1
  例のxamlがイレギュラーなのでしたいことをくみ取れている自信はありませんが、探しているのは`VisualTreeHelper`ですかね?
2
2
 
3
-
4
-
5
- ```xaml
3
+ ```xml
6
-
7
4
  <Window
8
-
9
5
  x:Class="Questions299424.MainWindow"
10
-
11
6
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
12
-
13
7
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
14
-
15
8
  Width="800"
16
-
17
9
  Height="450"
18
-
19
10
  Loaded="Window_Loaded">
20
-
21
11
  <Grid>
22
-
23
12
  <Button x:Name="BTN" Click="BTN_Click">
24
-
25
13
  <Canvas>
26
-
27
14
  <Label x:Name="LBL" Content="ラベルのテキスト" />
28
-
29
15
  </Canvas>
30
-
31
16
  </Button>
32
-
33
17
  </Grid>
34
-
35
18
  </Window>
36
-
37
19
  ```
38
20
 
39
-
40
-
41
- ```C#
21
+ ```cs
42
-
43
22
  using System;
44
-
45
23
  using System.Collections.Generic;
46
-
47
24
  using System.Linq;
48
-
49
25
  using System.Windows;
50
-
51
26
  using System.Windows.Controls;
52
-
53
27
  using System.Windows.Media;
54
28
 
55
-
56
-
57
29
  namespace Questions299424
58
-
59
30
  {
60
-
61
31
  public partial class MainWindow : Window
62
-
63
32
  {
64
-
65
33
  public MainWindow()
66
-
67
34
  {
68
-
69
35
  InitializeComponent();
70
36
 
71
-
72
-
73
37
  // こういうことじゃないんですよね?
74
-
75
38
  string label_text = (string)LBL.Content;
76
39
 
77
-
78
-
79
40
  // 構造が固定で決め打ちでいいならこう?
80
-
81
41
  string label_text2 = (string)((Label)((Canvas)BTN.Content).Children[0]).Content;
82
42
 
83
-
84
-
85
43
  // ↑キャストの順が逆に見えて直感的じゃないのでこうのほうが見やすい?
86
-
87
44
  string label_text3 = ((BTN.Content as Canvas).Children[0] as Label).Content as string;
88
45
 
89
-
90
-
91
46
  // 構造が違ってもエラーは出ないようにする(もちろん違ったら取得もできない)
92
-
93
47
  string label_text4 = (BTN.Content as Canvas)?.Children.OfType<Label>().FirstOrDefault()?.Content as string;
94
48
 
95
-
96
-
97
49
  // この時点ではVisualTreeが出来てないのでまだ取れない
98
-
99
50
  string label_text5 = BTN.Descendants<TextBlock>().FirstOrDefault()?.Text;
100
-
101
51
  }
102
52
 
103
-
104
-
105
53
  private void Window_Loaded(object sender, RoutedEventArgs e)
106
-
107
54
  {
108
-
109
55
  // Loaded以降ならOK
110
-
111
56
  string label_text = BTN.Descendants<TextBlock>().FirstOrDefault()?.Text;
112
-
113
57
  }
114
58
 
115
-
116
-
117
59
  private void BTN_Click(object sender, RoutedEventArgs e)
118
-
119
60
  {
120
-
121
61
  if(sender is Button button)
122
-
123
62
  {
124
-
125
63
  // Buttonの子孫で最初に見つかったLabelのContent
126
-
127
64
  string label_text = button.Descendants<Label>().FirstOrDefault()?.Content as string;
128
65
 
66
+ // ならいっそTextBlockを探す
67
+ string label_text2 = button.Descendants<TextBlock>().FirstOrDefault()?.Text;
68
+ }
69
+ }
70
+ }
129
71
 
72
+ // [VisualTreeの子孫要素を取得する - xin9le.net](https://blog.xin9le.net/entry/2013/10/29/222336)
73
+ public static class DependencyObjectExtensions
74
+ {
75
+ //--- 子要素を取得
76
+ public static IEnumerable<DependencyObject> Children(this DependencyObject obj)
77
+ {
78
+ if(obj == null) throw new ArgumentNullException("obj");
130
79
 
80
+ var count = VisualTreeHelper.GetChildrenCount(obj);
131
- // ならいっそTextBlockを探す
81
+ if(count == 0) yield break;
132
82
 
83
+ for(var i = 0; i < count; i++)
84
+ {
133
- string label_text2 = button.Descendants<TextBlock>().FirstOrDefault()?.Text;
85
+ var child = VisualTreeHelper.GetChild(obj, i);
134
-
86
+ if(child != null) yield return child;
135
87
  }
136
-
137
88
  }
138
89
 
139
- }
140
-
141
-
142
-
143
- // [VisualTreeの子孫要素を取得する - xin9le.net](https://blog.xin9le.net/entry/2013/10/29/222336)
144
-
145
- public static class DependencyObjectExtensions
146
-
147
- {
148
-
149
- //--- 子要素を取得
90
+ //--- 子要素を取得
150
-
151
- public static IEnumerable<DependencyObject> Children(this DependencyObject obj)
91
+ public static IEnumerable<DependencyObject> Descendants(this DependencyObject obj)
152
-
153
92
  {
154
-
155
93
  if(obj == null) throw new ArgumentNullException("obj");
156
94
 
157
-
158
-
159
- var count = VisualTreeHelper.GetChildrenCount(obj);
160
-
161
- if(count == 0) yield break;
162
-
163
-
164
-
165
- for(var i = 0; i < count; i++)
95
+ foreach(var child in obj.Children())
166
-
167
96
  {
168
-
169
- var child = VisualTreeHelper.GetChild(obj, i);
170
-
171
- if(child != null) yield return child;
97
+ yield return child;
172
-
98
+ foreach(var grandChild in child.Descendants())
99
+ yield return grandChild;
173
100
  }
174
-
175
101
  }
176
102
 
177
-
178
-
179
- //--- 子孫要素を取得
180
-
181
- public static IEnumerable<DependencyObject> Descendants(this DependencyObject obj)
182
-
183
- {
184
-
185
- if(obj == null) throw new ArgumentNullException("obj");
186
-
187
-
188
-
189
- foreach(var child in obj.Children())
190
-
191
- {
192
-
193
- yield return child;
194
-
195
- foreach(var grandChild in child.Descendants())
196
-
197
- yield return grandChild;
198
-
199
- }
200
-
201
- }
202
-
203
-
204
-
205
103
  //--- 特定の型の子要素を取得
206
-
207
104
  public static IEnumerable<T> Children<T>(this DependencyObject obj)
208
-
209
105
  where T : DependencyObject => obj.Children().OfType<T>();
210
106
 
211
-
212
-
213
107
  //--- 特定の型の子孫要素を取得
214
-
215
108
  public static IEnumerable<T> Descendants<T>(this DependencyObject obj)
216
-
217
109
  where T : DependencyObject => obj.Descendants().OfType<T>();
218
-
219
110
  }
220
-
221
111
  }
222
-
223
112
  ```
224
113
 
225
-
226
-
227
114
  参考
228
-
229
115
  [VisualTreeの子孫要素を取得する - xin9le.net](https://blog.xin9le.net/entry/2013/10/29/222336)
230
-
231
-
232
116
 
233
117
  ---
234
118
 
235
-
236
-
237
119
  > なるべくテンプレートなどを使わない方法&FindNameなどの、文字列を検索しない方法のものを探しています。
238
-
239
120
  > Buttonコントロール自体にcontentは入れない方法でお願いします。
240
121
 
241
-
242
-
243
122
  やりたいことを説明するのが難しいのかもしれませんが、初心者という自覚があるなら最初から手法を制限されないほうがよろしいかと思います。
244
-
245
123
  もっと良い方法があっても提案できません(この件でもっと良い方法があるかはわかりません^^;