回答編集履歴

2

見直しキャンペーン中

2023/08/12 09:40

投稿

TN8001
TN8001

スコア9884

test CHANGED
@@ -123,6 +123,7 @@
123
123
  }
124
124
  }
125
125
  ```
126
+ ![アプリ動画](https://ddjkaamml8q8x.cloudfront.net/questions/2023-08-12/52e5e08d-6105-4ce0-b7ec-b89d5fd49950.gif)
126
127
 
127
128
  ---
128
129
 

1

見直しキャンペーン中

2023/07/23 05:43

投稿

TN8001
TN8001

スコア9884

test CHANGED
@@ -1,255 +1,129 @@
1
1
  > カーソルを合わせても何も起こらないListBoxの作成方法
2
-
3
-
4
2
 
5
3
  `ItemsControl`がそれです。
6
4
 
7
-
8
-
9
5
  > 1要素の追加と削除に対しての効率的な文字列への変換方法
10
6
 
11
-
12
-
13
7
  動かしてみた感じ、コード部分のせいではなく`TextBlock`の反映が遅いような気がします(ボタンの連打はできるが、表示がついてこない)
14
-
15
8
  行数の多い`TextBlock`自体が重いとなると、やはり仮想化を有効にした`ItemsControl`が最適です。
16
-
17
-
18
9
 
19
10
  `TextBlock.Inlines`に`Run`を追加削除もやってみましたが、お話にならないぐらい遅かったです。
20
11
 
21
-
22
-
23
- ```xaml
12
+ ```xml
24
-
25
13
  <Window
26
-
27
14
  x:Class="Questions291838.MainWindow"
28
-
29
15
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
30
-
31
16
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
32
-
33
17
  Width="800"
34
-
35
18
  Height="450">
36
-
37
19
  <Grid>
38
-
39
20
  <Grid.ColumnDefinitions>
40
-
41
21
  <ColumnDefinition />
42
-
43
22
  <ColumnDefinition />
44
-
45
23
  </Grid.ColumnDefinitions>
46
24
 
47
-
48
-
49
25
  <GroupBox Header="TextBlock">
50
-
51
26
  <DockPanel>
52
-
53
27
  <Button
54
-
55
28
  Click="TextBlockButton_Click"
56
-
57
29
  Content="Add"
58
-
59
30
  DockPanel.Dock="Top" />
60
-
61
31
  <ScrollViewer VerticalScrollBarVisibility="Auto">
62
-
63
32
  <TextBlock x:Name="tb" />
64
-
65
33
  </ScrollViewer>
66
-
67
34
  </DockPanel>
68
-
69
35
  </GroupBox>
70
36
 
71
-
72
-
73
37
  <GroupBox Grid.Column="1" Header="ItemsControl">
74
-
75
38
  <DockPanel>
76
-
77
39
  <Button
78
-
79
40
  Click="ItemsControlButton_Click"
80
-
81
41
  Content="Add"
82
-
83
42
  DockPanel.Dock="Top" />
84
-
85
43
  <ItemsControl x:Name="ic">
86
-
87
44
  <ItemsControl.ItemsPanel>
88
-
89
45
  <ItemsPanelTemplate>
90
-
91
46
  <VirtualizingStackPanel />
92
-
93
47
  </ItemsPanelTemplate>
94
-
95
48
  </ItemsControl.ItemsPanel>
96
-
97
49
  <ItemsControl.Template>
98
-
99
50
  <ControlTemplate>
100
-
101
51
  <ScrollViewer VerticalScrollBarVisibility="Auto">
102
-
103
52
  <ItemsPresenter />
104
-
105
53
  </ScrollViewer>
106
-
107
54
  </ControlTemplate>
108
-
109
55
  </ItemsControl.Template>
110
-
111
56
  </ItemsControl>
112
-
113
57
  </DockPanel>
114
-
115
58
  </GroupBox>
116
-
117
59
  </Grid>
118
-
119
60
  </Window>
120
-
121
61
  ```
122
62
 
123
- ```C#
63
+ ```cs
124
-
125
64
  using System;
126
-
127
65
  using System.Collections.Generic;
128
-
129
66
  using System.Collections.ObjectModel;
130
-
131
67
  using System.Linq;
132
-
133
68
  using System.Windows;
134
69
 
135
-
136
-
137
70
  namespace Questions291838
138
-
139
71
  {
140
-
141
72
  public partial class MainWindow : Window
142
-
143
73
  {
144
-
145
74
  private const int maxCount = 2000;
146
-
147
75
  private const string letters = "abcdefghijklmnopqrstuvwxyz";
148
76
 
149
-
150
-
151
77
  private readonly List<string> tbLogs = new List<string>();
152
-
153
78
  private readonly ObservableCollection<string> icLogs = new ObservableCollection<string>();
154
-
155
79
  private readonly Random r = new Random();
156
80
 
157
-
158
-
159
81
  public MainWindow()
160
-
161
82
  {
162
-
163
83
  InitializeComponent();
164
84
 
165
-
166
-
167
85
  for(var i = 0; i < maxCount; i++)
168
-
169
86
  {
170
-
171
87
  tbLogs.Add(RandomWord());
172
-
173
88
  icLogs.Add(RandomWord());
174
-
175
89
  }
176
-
177
90
  tb.Text = string.Join("\n", tbLogs);
178
-
179
91
  ic.ItemsSource = icLogs;
180
-
181
92
  }
182
93
 
183
-
184
-
185
94
  // TextBlock側をできるだけ有利にしたつもり
186
-
187
95
  // 「少しは速くなるかな?」と思い書き換えた部分があるが、特にベンチマークを取ったわけではない
188
-
189
96
  private void TextBlockButton_Click(object sender, RoutedEventArgs e)
190
-
191
97
  {
192
-
193
98
  for(var i = 0; i < 10; i++)
194
-
195
99
  {
196
-
197
100
  tbLogs.Insert(0, RandomWord());
198
-
199
101
  }
200
-
201
102
  if(tbLogs.Count > maxCount)
202
-
203
103
  {
204
-
205
104
  tbLogs.RemoveRange(maxCount, tbLogs.Count - maxCount);
206
-
207
105
  }
208
-
209
106
  tb.Text = string.Join("\n", tbLogs);
210
-
211
107
  }
212
108
 
213
-
214
-
215
109
  private void ItemsControlButton_Click(object sender, RoutedEventArgs e)
216
-
217
110
  {
218
-
219
111
  for(var i = 0; i < 10; i++)
220
-
221
112
  {
222
-
223
113
  icLogs.Insert(0, RandomWord());
224
-
225
114
  while(icLogs.Count > maxCount)
226
-
227
115
  {
228
-
229
116
  icLogs.RemoveAt(icLogs.Count - 1);
230
-
231
117
  }
232
-
233
118
  }
234
-
235
119
  }
236
120
 
237
-
238
-
239
121
  // 1行にしたかっただけ 速さはしらない^^;
240
-
241
122
  private string RandomWord() => string.Join("", Enumerable.Range(0, r.Next(1, 20)).Select(x => letters[r.Next(0, letters.Length - 1)]));
242
-
243
123
  }
244
-
245
124
  }
246
-
247
125
  ```
248
-
249
-
250
126
 
251
127
  ---
252
128
 
253
-
254
-
255
129
  さらに改良の余地もありそうですが、体感では差がわからなそうなのでやめました^^;