回答編集履歴

2

見直しキャンペーン中

2023/07/22 08:48

投稿

TN8001
TN8001

スコア9862

test CHANGED
@@ -1,379 +1,191 @@
1
1
  `DragDelta`はクリックした位置からの差分なので、毎回足していくとどんどん伸びることになります。
2
-
3
2
  前回の`HorizontalChange`を引くか、クリックした時の`Width`を覚えておくかになると思います。
4
-
5
3
  そうなると`DragStarted`や`DragCompleted`の監視が必要になりそうです。
6
4
 
7
-
8
-
9
5
  そもそもとして左端の`Thumb`はいいですが、右のほうの`Thumb`はサイズが変わったことで移動してしまい`DragDelta`が大きく暴れてしまいます。
10
-
11
6
  `DragDelta`が使えないとなると、`Mouse.GetPosition(Application.Current.MainWindow).X`とかになるでしょうが「どうなの?」って気はします。
12
-
13
-
14
7
 
15
8
  もうすこし用途というかシナリオが分かればいい方法もありそうな気がしますが、かなり凝ったことをされているようなので説明しづらいでしょうね^^;
16
9
 
10
+ ---
17
11
 
12
+ 検証中はMVVMにこだわらずコードビハインドに書いていいと思います。
13
+ 希望の動作になったら移せばいいので。
18
14
 
19
15
  ---
20
16
 
21
-
22
-
23
- 検証中はMVVMにこだわらずコードビハインドに書いていいと思います。
24
-
25
- 希望の動作になったら移せばいいので。
26
-
27
-
28
-
29
17
  追記
30
-
31
- ---
32
-
33
-
34
-
35
18
  一応それっぽくはなったのですが、非常に泥臭くなってしまいました^^;
36
-
37
19
  これはビヘイビアにするのが正攻法でしょうね(ViewModelでやる処理じゃないですね)
38
20
 
39
-
40
-
41
21
  **注意**
42
-
43
22
  * Prism.Coreだけ入れました
44
-
45
23
  * 構造は全部決め打ちです
46
-
47
24
  * 画像のサイズが同じという前提です(違うならサイズでなくてマージンで調整か?)
48
-
49
25
  * 縦線や半透明ピンクは確認用なので深い意味はないです
50
-
51
- * Rectangleなのも特に意味はないです
26
+ * `Rectangle`なのも特に意味はないです
52
-
53
27
  * 画像も確認用なので特に意味はないです
54
28
 
29
+ `Width`・`Height`のバインディングが必要ないなら、`ItemsControl`自体のドラッグで全ての`ContentPresenter`をリサイズするほうが簡単そうな気もします(位置補正まですると大差ないかもしれない)
55
30
 
56
-
57
- Width Heightのバインディングが必要ないなら、`ItemsControl`自体のドラッグで全ての`ContentPresenter`をリサイズするほうが簡単そうな気もします(位置補正まですると大差ないかもしれない)
58
-
59
-
60
-
61
- ```xaml
31
+ ```xml
62
-
63
32
  <Window
64
-
65
33
  x:Class="Questions276037.MainWindow"
66
-
67
34
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
68
-
69
35
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
70
-
71
36
  Width="525"
72
-
73
37
  Height="350">
74
-
75
38
  <Window.Resources>
76
-
77
39
  <!-- 個々のアイテム -->
78
-
79
40
  <DataTemplate x:Key="itemTemplate">
80
-
81
41
  <Grid>
82
-
83
42
  <Image
84
-
85
43
  x:Name="image"
86
-
87
44
  HorizontalAlignment="Center"
88
-
89
45
  VerticalAlignment="Center"
90
-
91
46
  Source="{Binding Source}" />
92
-
93
47
  <Rectangle
94
-
95
48
  Width="{Binding Width}"
96
-
97
49
  Height="{Binding Height}"
98
-
99
50
  MinWidth="{Binding ActualWidth, ElementName=image}"
100
-
101
51
  MinHeight="{Binding ActualHeight, ElementName=image}"
102
-
103
52
  Fill="#4CFF0000"
104
-
105
53
  MouseDown="Rectangle_MouseDown"
106
-
107
54
  MouseMove="Rectangle_MouseMove"
108
-
109
55
  MouseUp="Rectangle_MouseUp" />
110
-
111
56
  </Grid>
112
-
113
57
  </DataTemplate>
114
58
 
115
-
116
-
117
59
  <!-- 目印用グリッド線 -->
118
-
119
60
  <VisualBrush
120
-
121
61
  x:Key="lineBrush"
122
-
123
62
  TileMode="Tile"
124
-
125
63
  Viewbox="0,0,25,25"
126
-
127
64
  ViewboxUnits="Absolute"
128
-
129
65
  Viewport="0,0,25,25"
130
-
131
66
  ViewportUnits="Absolute">
132
-
133
67
  <VisualBrush.Visual>
134
-
135
68
  <Path Data="M0,0L0,25" Stroke="Gray" />
136
-
137
69
  </VisualBrush.Visual>
138
-
139
70
  </VisualBrush>
140
-
141
71
  </Window.Resources>
142
72
 
143
-
144
-
145
73
  <ItemsControl ItemTemplate="{StaticResource itemTemplate}" ItemsSource="{Binding List}">
146
-
147
74
  <ItemsControl.Template>
148
-
149
75
  <ControlTemplate>
150
-
151
76
  <ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
152
-
153
77
  <ItemsPresenter />
154
-
155
78
  </ScrollViewer>
156
-
157
79
  </ControlTemplate>
158
-
159
80
  </ItemsControl.Template>
160
-
161
81
  <ItemsControl.ItemsPanel>
162
-
163
82
  <ItemsPanelTemplate>
164
-
165
83
  <StackPanel Background="{StaticResource lineBrush}" Orientation="Horizontal" />
166
-
167
84
  </ItemsPanelTemplate>
168
-
169
85
  </ItemsControl.ItemsPanel>
170
-
171
86
  </ItemsControl>
172
-
173
87
  </Window>
174
-
175
88
  ```
176
89
 
177
-
178
-
179
- ```C#
90
+ ```cs
180
-
181
91
  using System;
182
-
183
92
  using System.Collections.ObjectModel;
184
-
185
93
  using System.Windows;
186
-
187
94
  using System.Windows.Controls;
188
-
189
95
  using System.Windows.Input;
190
-
191
96
  using System.Windows.Media;
192
-
193
97
  using System.Windows.Media.Imaging;
194
-
195
98
  using System.Windows.Shapes;
196
-
197
99
  using Prism.Mvvm;
198
100
 
199
-
200
-
201
101
  namespace Questions276037
202
-
203
102
  {
204
-
205
103
  public partial class MainWindow : Window
206
-
207
104
  {
208
-
209
105
  private readonly BitmapImage i1 = new BitmapImage(new Uri("https://teratail-v2.storage.googleapis.com/uploads/avatars/u13/132786/KnkDDC5A_thumbnail.jpg"));
210
-
211
106
  private readonly BitmapImage i2 = new BitmapImage(new Uri("https://teratail-v2.storage.googleapis.com/uploads/avatars/u10/105091/d8tKNb7D_thumbnail.jpg"));
212
-
213
-
214
107
 
215
108
  public ObservableCollection<Item> List { get; } = new ObservableCollection<Item>();
216
109
 
217
-
218
-
219
110
  public MainWindow()
220
-
221
111
  {
222
-
223
112
  InitializeComponent();
224
113
 
225
-
226
-
227
114
  for(var i = 0; i < 5; i++)
228
-
229
115
  {
230
-
231
116
  List.Add(new Item() { Width = 95, Height = 95, Source = i1, });
232
-
233
117
  List.Add(new Item() { Width = 95, Height = 95, Source = i2, });
234
-
235
118
  }
236
-
237
119
  DataContext = this;
238
-
239
120
  }
240
121
 
241
-
242
-
243
122
  private Point oldPos;
244
-
245
123
  private bool dragging;
246
124
 
247
-
248
-
249
125
  private void Rectangle_MouseDown(object sender, MouseButtonEventArgs e)
250
-
251
126
  {
252
-
253
127
  dragging = true;
128
+ var rectangle = sender as Rectangle;
129
+ rectangle.CaptureMouse();
130
+ oldPos = Mouse.GetPosition(null);
131
+ }
132
+ private void Rectangle_MouseMove(object sender, MouseEventArgs e)
133
+ {
134
+ if(!dragging) return;
254
135
 
255
136
  var rectangle = sender as Rectangle;
256
-
257
- rectangle.CaptureMouse();
258
-
259
- oldPos = Mouse.GetPosition(null);
260
-
261
- }
262
-
263
- private void Rectangle_MouseMove(object sender, MouseEventArgs e)
264
-
265
- {
266
-
267
- if(!dragging) return;
268
-
269
-
270
-
271
- var rectangle = sender as Rectangle;
272
-
273
137
  var newPos = Mouse.GetPosition(null);
274
-
275
138
  var deltaX = newPos.X - oldPos.X;
276
-
277
139
  oldPos = newPos;
278
-
279
-
280
140
 
281
141
  if(rectangle.Width + deltaX < rectangle.MinWidth) return; // 画像より小さくしない
282
142
 
283
-
284
-
285
143
  var contentPresenter = rectangle.FindAncestor<ContentPresenter>();
286
-
287
144
  var stackPanel = rectangle.FindAncestor<StackPanel>();
288
-
289
145
  var scrollViewer = rectangle.FindAncestor<ScrollViewer>();
290
-
291
146
  var itemsControl = rectangle.FindAncestor<ItemsControl>();
292
147
 
293
-
294
-
295
148
  foreach(Item item in itemsControl.Items)
296
-
297
149
  item.Width += deltaX;
298
150
 
299
-
300
-
301
151
  var offset = scrollViewer.TranslatePoint(new Point(), stackPanel); // StackPanelがScrollViewerからはみ出た長さ
302
-
303
152
  var index = itemsControl.ItemContainerGenerator.IndexFromContainer(contentPresenter);
304
-
305
153
  var total = (index + 1 - 0.5) * deltaX; // カーソル左側の伸びた分合計
306
154
 
307
-
308
-
309
155
  scrollViewer.ScrollToHorizontalOffset(offset.X + total); // スクロールバー調整
310
-
311
156
  }
312
157
 
313
-
314
-
315
158
  private void Rectangle_MouseUp(object sender, MouseButtonEventArgs e)
316
-
317
159
  {
318
-
319
160
  dragging = false;
320
-
321
161
  var rectangle = sender as Rectangle;
322
-
323
162
  rectangle.ReleaseMouseCapture();
324
-
325
163
  oldPos = new Point();
326
-
327
164
  }
328
-
329
165
  }
330
166
 
331
-
332
-
333
167
  public class Item : BindableBase
334
-
335
168
  {
336
-
337
169
  private double _width = 0;
338
-
339
170
  private double _height = 0;
340
-
341
171
  public double Width { get => _width; set => SetProperty(ref _width, value); }
342
-
343
172
  public double Height { get => _height; set => SetProperty(ref _height, value); }
344
-
345
173
  public BitmapImage Source { get; set; }
346
-
347
174
  }
348
175
 
349
-
350
-
351
176
  internal static class DependencyObjectExtensions
352
-
353
177
  {
354
-
355
178
  public static T FindAncestor<T>(this DependencyObject obj) where T : DependencyObject
356
-
357
179
  {
358
-
359
180
  do
360
-
361
181
  {
362
-
363
182
  obj = VisualTreeHelper.GetParent(obj);
364
-
365
183
  if(obj == null) return null;
366
-
367
184
  } while(!(obj is T));
368
185
 
369
-
370
-
371
186
  return obj as T;
372
-
373
187
  }
374
-
375
188
  }
376
-
377
189
  }
378
-
379
190
  ```
191
+ ![アプリ動画](https://ddjkaamml8q8x.cloudfront.net/questions/2023-07-22/982627ad-5a92-4d08-ae0f-17b33d79675a.gif)

1

コード追記

2020/07/08 23:23

投稿

TN8001
TN8001

スコア9862

test CHANGED
@@ -23,3 +23,357 @@
23
23
  検証中はMVVMにこだわらずコードビハインドに書いていいと思います。
24
24
 
25
25
  希望の動作になったら移せばいいので。
26
+
27
+
28
+
29
+ 追記
30
+
31
+ ---
32
+
33
+
34
+
35
+ 一応それっぽくはなったのですが、非常に泥臭くなってしまいました^^;
36
+
37
+ これはビヘイビアにするのが正攻法でしょうね(ViewModelでやる処理じゃないですね)
38
+
39
+
40
+
41
+ **注意**
42
+
43
+ * Prism.Coreだけ入れました
44
+
45
+ * 構造は全部決め打ちです
46
+
47
+ * 画像のサイズが同じという前提です(違うならサイズでなくてマージンで調整か?)
48
+
49
+ * 縦線や半透明ピンクは確認用なので深い意味はないです
50
+
51
+ * Rectangleなのも特に意味はないです
52
+
53
+ * 画像も確認用なので特に意味はないです
54
+
55
+
56
+
57
+ Width Heightのバインディングが必要ないなら、`ItemsControl`自体のドラッグで全ての`ContentPresenter`をリサイズするほうが簡単そうな気もします(位置補正まですると大差ないかもしれない)
58
+
59
+
60
+
61
+ ```xaml
62
+
63
+ <Window
64
+
65
+ x:Class="Questions276037.MainWindow"
66
+
67
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
68
+
69
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
70
+
71
+ Width="525"
72
+
73
+ Height="350">
74
+
75
+ <Window.Resources>
76
+
77
+ <!-- 個々のアイテム -->
78
+
79
+ <DataTemplate x:Key="itemTemplate">
80
+
81
+ <Grid>
82
+
83
+ <Image
84
+
85
+ x:Name="image"
86
+
87
+ HorizontalAlignment="Center"
88
+
89
+ VerticalAlignment="Center"
90
+
91
+ Source="{Binding Source}" />
92
+
93
+ <Rectangle
94
+
95
+ Width="{Binding Width}"
96
+
97
+ Height="{Binding Height}"
98
+
99
+ MinWidth="{Binding ActualWidth, ElementName=image}"
100
+
101
+ MinHeight="{Binding ActualHeight, ElementName=image}"
102
+
103
+ Fill="#4CFF0000"
104
+
105
+ MouseDown="Rectangle_MouseDown"
106
+
107
+ MouseMove="Rectangle_MouseMove"
108
+
109
+ MouseUp="Rectangle_MouseUp" />
110
+
111
+ </Grid>
112
+
113
+ </DataTemplate>
114
+
115
+
116
+
117
+ <!-- 目印用グリッド線 -->
118
+
119
+ <VisualBrush
120
+
121
+ x:Key="lineBrush"
122
+
123
+ TileMode="Tile"
124
+
125
+ Viewbox="0,0,25,25"
126
+
127
+ ViewboxUnits="Absolute"
128
+
129
+ Viewport="0,0,25,25"
130
+
131
+ ViewportUnits="Absolute">
132
+
133
+ <VisualBrush.Visual>
134
+
135
+ <Path Data="M0,0L0,25" Stroke="Gray" />
136
+
137
+ </VisualBrush.Visual>
138
+
139
+ </VisualBrush>
140
+
141
+ </Window.Resources>
142
+
143
+
144
+
145
+ <ItemsControl ItemTemplate="{StaticResource itemTemplate}" ItemsSource="{Binding List}">
146
+
147
+ <ItemsControl.Template>
148
+
149
+ <ControlTemplate>
150
+
151
+ <ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
152
+
153
+ <ItemsPresenter />
154
+
155
+ </ScrollViewer>
156
+
157
+ </ControlTemplate>
158
+
159
+ </ItemsControl.Template>
160
+
161
+ <ItemsControl.ItemsPanel>
162
+
163
+ <ItemsPanelTemplate>
164
+
165
+ <StackPanel Background="{StaticResource lineBrush}" Orientation="Horizontal" />
166
+
167
+ </ItemsPanelTemplate>
168
+
169
+ </ItemsControl.ItemsPanel>
170
+
171
+ </ItemsControl>
172
+
173
+ </Window>
174
+
175
+ ```
176
+
177
+
178
+
179
+ ```C#
180
+
181
+ using System;
182
+
183
+ using System.Collections.ObjectModel;
184
+
185
+ using System.Windows;
186
+
187
+ using System.Windows.Controls;
188
+
189
+ using System.Windows.Input;
190
+
191
+ using System.Windows.Media;
192
+
193
+ using System.Windows.Media.Imaging;
194
+
195
+ using System.Windows.Shapes;
196
+
197
+ using Prism.Mvvm;
198
+
199
+
200
+
201
+ namespace Questions276037
202
+
203
+ {
204
+
205
+ public partial class MainWindow : Window
206
+
207
+ {
208
+
209
+ private readonly BitmapImage i1 = new BitmapImage(new Uri("https://teratail-v2.storage.googleapis.com/uploads/avatars/u13/132786/KnkDDC5A_thumbnail.jpg"));
210
+
211
+ private readonly BitmapImage i2 = new BitmapImage(new Uri("https://teratail-v2.storage.googleapis.com/uploads/avatars/u10/105091/d8tKNb7D_thumbnail.jpg"));
212
+
213
+
214
+
215
+ public ObservableCollection<Item> List { get; } = new ObservableCollection<Item>();
216
+
217
+
218
+
219
+ public MainWindow()
220
+
221
+ {
222
+
223
+ InitializeComponent();
224
+
225
+
226
+
227
+ for(var i = 0; i < 5; i++)
228
+
229
+ {
230
+
231
+ List.Add(new Item() { Width = 95, Height = 95, Source = i1, });
232
+
233
+ List.Add(new Item() { Width = 95, Height = 95, Source = i2, });
234
+
235
+ }
236
+
237
+ DataContext = this;
238
+
239
+ }
240
+
241
+
242
+
243
+ private Point oldPos;
244
+
245
+ private bool dragging;
246
+
247
+
248
+
249
+ private void Rectangle_MouseDown(object sender, MouseButtonEventArgs e)
250
+
251
+ {
252
+
253
+ dragging = true;
254
+
255
+ var rectangle = sender as Rectangle;
256
+
257
+ rectangle.CaptureMouse();
258
+
259
+ oldPos = Mouse.GetPosition(null);
260
+
261
+ }
262
+
263
+ private void Rectangle_MouseMove(object sender, MouseEventArgs e)
264
+
265
+ {
266
+
267
+ if(!dragging) return;
268
+
269
+
270
+
271
+ var rectangle = sender as Rectangle;
272
+
273
+ var newPos = Mouse.GetPosition(null);
274
+
275
+ var deltaX = newPos.X - oldPos.X;
276
+
277
+ oldPos = newPos;
278
+
279
+
280
+
281
+ if(rectangle.Width + deltaX < rectangle.MinWidth) return; // 画像より小さくしない
282
+
283
+
284
+
285
+ var contentPresenter = rectangle.FindAncestor<ContentPresenter>();
286
+
287
+ var stackPanel = rectangle.FindAncestor<StackPanel>();
288
+
289
+ var scrollViewer = rectangle.FindAncestor<ScrollViewer>();
290
+
291
+ var itemsControl = rectangle.FindAncestor<ItemsControl>();
292
+
293
+
294
+
295
+ foreach(Item item in itemsControl.Items)
296
+
297
+ item.Width += deltaX;
298
+
299
+
300
+
301
+ var offset = scrollViewer.TranslatePoint(new Point(), stackPanel); // StackPanelがScrollViewerからはみ出た長さ
302
+
303
+ var index = itemsControl.ItemContainerGenerator.IndexFromContainer(contentPresenter);
304
+
305
+ var total = (index + 1 - 0.5) * deltaX; // カーソル左側の伸びた分合計
306
+
307
+
308
+
309
+ scrollViewer.ScrollToHorizontalOffset(offset.X + total); // スクロールバー調整
310
+
311
+ }
312
+
313
+
314
+
315
+ private void Rectangle_MouseUp(object sender, MouseButtonEventArgs e)
316
+
317
+ {
318
+
319
+ dragging = false;
320
+
321
+ var rectangle = sender as Rectangle;
322
+
323
+ rectangle.ReleaseMouseCapture();
324
+
325
+ oldPos = new Point();
326
+
327
+ }
328
+
329
+ }
330
+
331
+
332
+
333
+ public class Item : BindableBase
334
+
335
+ {
336
+
337
+ private double _width = 0;
338
+
339
+ private double _height = 0;
340
+
341
+ public double Width { get => _width; set => SetProperty(ref _width, value); }
342
+
343
+ public double Height { get => _height; set => SetProperty(ref _height, value); }
344
+
345
+ public BitmapImage Source { get; set; }
346
+
347
+ }
348
+
349
+
350
+
351
+ internal static class DependencyObjectExtensions
352
+
353
+ {
354
+
355
+ public static T FindAncestor<T>(this DependencyObject obj) where T : DependencyObject
356
+
357
+ {
358
+
359
+ do
360
+
361
+ {
362
+
363
+ obj = VisualTreeHelper.GetParent(obj);
364
+
365
+ if(obj == null) return null;
366
+
367
+ } while(!(obj is T));
368
+
369
+
370
+
371
+ return obj as T;
372
+
373
+ }
374
+
375
+ }
376
+
377
+ }
378
+
379
+ ```