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

回答編集履歴

1

見直しキャンペーン中

2023/07/23 08:13

投稿

TN8001
TN8001

スコア10095

answer CHANGED
@@ -1,123 +1,123 @@
1
- 例のxamlがイレギュラーなのでしたいことをくみ取れている自信はありませんが、探しているのは`VisualTreeHelper`ですかね?
2
-
3
- ```xaml
4
- <Window
5
- x:Class="Questions299424.MainWindow"
6
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
7
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
8
- Width="800"
9
- Height="450"
10
- Loaded="Window_Loaded">
11
- <Grid>
12
- <Button x:Name="BTN" Click="BTN_Click">
13
- <Canvas>
14
- <Label x:Name="LBL" Content="ラベルのテキスト" />
15
- </Canvas>
16
- </Button>
17
- </Grid>
18
- </Window>
19
- ```
20
-
21
- ```C#
22
- using System;
23
- using System.Collections.Generic;
24
- using System.Linq;
25
- using System.Windows;
26
- using System.Windows.Controls;
27
- using System.Windows.Media;
28
-
29
- namespace Questions299424
30
- {
31
- public partial class MainWindow : Window
32
- {
33
- public MainWindow()
34
- {
35
- InitializeComponent();
36
-
37
- // こういうことじゃないんですよね?
38
- string label_text = (string)LBL.Content;
39
-
40
- // 構造が固定で決め打ちでいいならこう?
41
- string label_text2 = (string)((Label)((Canvas)BTN.Content).Children[0]).Content;
42
-
43
- // ↑キャストの順が逆に見えて直感的じゃないのでこうのほうが見やすい?
44
- string label_text3 = ((BTN.Content as Canvas).Children[0] as Label).Content as string;
45
-
46
- // 構造が違ってもエラーは出ないようにする(もちろん違ったら取得もできない)
47
- string label_text4 = (BTN.Content as Canvas)?.Children.OfType<Label>().FirstOrDefault()?.Content as string;
48
-
49
- // この時点ではVisualTreeが出来てないのでまだ取れない
50
- string label_text5 = BTN.Descendants<TextBlock>().FirstOrDefault()?.Text;
51
- }
52
-
53
- private void Window_Loaded(object sender, RoutedEventArgs e)
54
- {
55
- // Loaded以降ならOK
56
- string label_text = BTN.Descendants<TextBlock>().FirstOrDefault()?.Text;
57
- }
58
-
59
- private void BTN_Click(object sender, RoutedEventArgs e)
60
- {
61
- if(sender is Button button)
62
- {
63
- // Buttonの子孫で最初に見つかったLabelのContent
64
- string label_text = button.Descendants<Label>().FirstOrDefault()?.Content as string;
65
-
66
- // ならいっそTextBlockを探す
67
- string label_text2 = button.Descendants<TextBlock>().FirstOrDefault()?.Text;
68
- }
69
- }
70
- }
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");
79
-
80
- var count = VisualTreeHelper.GetChildrenCount(obj);
81
- if(count == 0) yield break;
82
-
83
- for(var i = 0; i < count; i++)
84
- {
85
- var child = VisualTreeHelper.GetChild(obj, i);
86
- if(child != null) yield return child;
87
- }
88
- }
89
-
90
- //--- 子孫要素を取得
91
- public static IEnumerable<DependencyObject> Descendants(this DependencyObject obj)
92
- {
93
- if(obj == null) throw new ArgumentNullException("obj");
94
-
95
- foreach(var child in obj.Children())
96
- {
97
- yield return child;
98
- foreach(var grandChild in child.Descendants())
99
- yield return grandChild;
100
- }
101
- }
102
-
103
- //--- 特定の型の子要素を取得
104
- public static IEnumerable<T> Children<T>(this DependencyObject obj)
105
- where T : DependencyObject => obj.Children().OfType<T>();
106
-
107
- //--- 特定の型の子孫要素を取得
108
- public static IEnumerable<T> Descendants<T>(this DependencyObject obj)
109
- where T : DependencyObject => obj.Descendants().OfType<T>();
110
- }
111
- }
112
- ```
113
-
114
- 参考
115
- [VisualTreeの子孫要素を取得する - xin9le.net](https://blog.xin9le.net/entry/2013/10/29/222336)
116
-
117
- ---
118
-
119
- > なるべくテンプレートなどを使わない方法&FindNameなどの、文字列を検索しない方法のものを探しています。
120
- > Buttonコントロール自体にcontentは入れない方法でお願いします。
121
-
122
- やりたいことを説明するのが難しいのかもしれませんが、初心者という自覚があるなら最初から手法を制限されないほうがよろしいかと思います。
1
+ 例のxamlがイレギュラーなのでしたいことをくみ取れている自信はありませんが、探しているのは`VisualTreeHelper`ですかね?
2
+
3
+ ```xml
4
+ <Window
5
+ x:Class="Questions299424.MainWindow"
6
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
7
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
8
+ Width="800"
9
+ Height="450"
10
+ Loaded="Window_Loaded">
11
+ <Grid>
12
+ <Button x:Name="BTN" Click="BTN_Click">
13
+ <Canvas>
14
+ <Label x:Name="LBL" Content="ラベルのテキスト" />
15
+ </Canvas>
16
+ </Button>
17
+ </Grid>
18
+ </Window>
19
+ ```
20
+
21
+ ```cs
22
+ using System;
23
+ using System.Collections.Generic;
24
+ using System.Linq;
25
+ using System.Windows;
26
+ using System.Windows.Controls;
27
+ using System.Windows.Media;
28
+
29
+ namespace Questions299424
30
+ {
31
+ public partial class MainWindow : Window
32
+ {
33
+ public MainWindow()
34
+ {
35
+ InitializeComponent();
36
+
37
+ // こういうことじゃないんですよね?
38
+ string label_text = (string)LBL.Content;
39
+
40
+ // 構造が固定で決め打ちでいいならこう?
41
+ string label_text2 = (string)((Label)((Canvas)BTN.Content).Children[0]).Content;
42
+
43
+ // ↑キャストの順が逆に見えて直感的じゃないのでこうのほうが見やすい?
44
+ string label_text3 = ((BTN.Content as Canvas).Children[0] as Label).Content as string;
45
+
46
+ // 構造が違ってもエラーは出ないようにする(もちろん違ったら取得もできない)
47
+ string label_text4 = (BTN.Content as Canvas)?.Children.OfType<Label>().FirstOrDefault()?.Content as string;
48
+
49
+ // この時点ではVisualTreeが出来てないのでまだ取れない
50
+ string label_text5 = BTN.Descendants<TextBlock>().FirstOrDefault()?.Text;
51
+ }
52
+
53
+ private void Window_Loaded(object sender, RoutedEventArgs e)
54
+ {
55
+ // Loaded以降ならOK
56
+ string label_text = BTN.Descendants<TextBlock>().FirstOrDefault()?.Text;
57
+ }
58
+
59
+ private void BTN_Click(object sender, RoutedEventArgs e)
60
+ {
61
+ if(sender is Button button)
62
+ {
63
+ // Buttonの子孫で最初に見つかったLabelのContent
64
+ string label_text = button.Descendants<Label>().FirstOrDefault()?.Content as string;
65
+
66
+ // ならいっそTextBlockを探す
67
+ string label_text2 = button.Descendants<TextBlock>().FirstOrDefault()?.Text;
68
+ }
69
+ }
70
+ }
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");
79
+
80
+ var count = VisualTreeHelper.GetChildrenCount(obj);
81
+ if(count == 0) yield break;
82
+
83
+ for(var i = 0; i < count; i++)
84
+ {
85
+ var child = VisualTreeHelper.GetChild(obj, i);
86
+ if(child != null) yield return child;
87
+ }
88
+ }
89
+
90
+ //--- 子孫要素を取得
91
+ public static IEnumerable<DependencyObject> Descendants(this DependencyObject obj)
92
+ {
93
+ if(obj == null) throw new ArgumentNullException("obj");
94
+
95
+ foreach(var child in obj.Children())
96
+ {
97
+ yield return child;
98
+ foreach(var grandChild in child.Descendants())
99
+ yield return grandChild;
100
+ }
101
+ }
102
+
103
+ //--- 特定の型の子要素を取得
104
+ public static IEnumerable<T> Children<T>(this DependencyObject obj)
105
+ where T : DependencyObject => obj.Children().OfType<T>();
106
+
107
+ //--- 特定の型の子孫要素を取得
108
+ public static IEnumerable<T> Descendants<T>(this DependencyObject obj)
109
+ where T : DependencyObject => obj.Descendants().OfType<T>();
110
+ }
111
+ }
112
+ ```
113
+
114
+ 参考
115
+ [VisualTreeの子孫要素を取得する - xin9le.net](https://blog.xin9le.net/entry/2013/10/29/222336)
116
+
117
+ ---
118
+
119
+ > なるべくテンプレートなどを使わない方法&FindNameなどの、文字列を検索しない方法のものを探しています。
120
+ > Buttonコントロール自体にcontentは入れない方法でお願いします。
121
+
122
+ やりたいことを説明するのが難しいのかもしれませんが、初心者という自覚があるなら最初から手法を制限されないほうがよろしいかと思います。
123
123
  もっと良い方法があっても提案できません(この件でもっと良い方法があるかはわかりません^^;