お世話になります。
調べたのですが、分からないため教えてください。
実現したいこと
【WPF】Excel 図形 みたいなのを作る
https://noitalog.tokyo/wpf-excel-shape/
上記のようにドラッグで四角形を動的に作成し、
作成済の四角形をクリックすると移動したり拡縮したりしたいです。
.NET6.0/C#10.0でオートシェイプ風図形描画ライブラリを作ろう!(Chapter5)
https://qiita.com/pierusan2010/items/531199fbff10477f3064
一番作ってみたいのは、上記のオートシェイプ描画です。
ライブラリとか色々と複雑になると分からないため、
・四角形のみ(Canvas上に作成する) →ソースコピペで出来ている〇
・ドラッグで四角形を動的生成できる →ソースコピペで出来ている〇
・動的生成した四角形をドラッグ移動したり拡縮ができる →できてない×
・ドラッグ時に画面表示の為だけに使ったRectangleは不要なので削除したい→できてない×
・動的生成した四角形を選択すると、四角形の変数とか値(X,Y,Width,Height…)の値を取得できる →できていない×
上記が実行したい内容です。
できていない×の所を出来るようにしたいです。
前提
【WPF】Excel 図形 みたいなのを作る
https://noitalog.tokyo/wpf-excel-shape/
上記のソースをお借りしております。
該当のソースコード
MyRect.cs
1 public class MyRect 2 { 3 public double X { get; set; } 4 public double Y { get; set; } 5 public double Width { get; set; } 6 public double Height { get; set; } 7 public Brush Stroke { get; set; } 8 public Brush Fill { get; set; } 9 10 public MyRect(double x, double y,double width ,double height,Brush stroke,Brush fill) 11 { 12 X = x; 13 Y = y; 14 Width = width; 15 Height = height; 16 Stroke = stroke; 17 Fill = fill; 18 19 } 20 }
MainWindow.xaml.cs
1 public partial class MainWindow : Window 2 { 3 bool isMouseDown = false; 4 Point StartPoint; 5 Point MovePoint; 6 Rectangle rectangle; 7 8 public ObservableCollection<MyRect> MyRects = new ObservableCollection<MyRect>(); 9 public MainWindow() 10 { 11 InitializeComponent(); 12 13 } 14 15 private void MyCanvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) 16 { 17 var point = e.GetPosition(MyCanvas); 18 19 //var leftOffset = point.X % 10;//罫線に合わせる必要はないためコメントアウト 20 //leftOffset = leftOffset < 5 ? -leftOffset : 10 - leftOffset; 21 //var topOffset = point.Y % 10; 22 //topOffset = topOffset < 5 ? -topOffset : 10 - topOffset; 23 var leftOffset = point.X; 24 var topOffset = point.Y; 25 26 StartPoint = new Point(point.X + leftOffset, point.Y + topOffset); 27 28 rectangle = new Rectangle 29 { 30 Stroke = Brushes.Black, 31 Fill = Brushes.LightBlue, 32 HorizontalAlignment = HorizontalAlignment.Left, 33 VerticalAlignment = VerticalAlignment.Top, 34 Width = 0, 35 Height = 0, 36 Opacity = 0.3 37 }; 38 39 Canvas.SetLeft(rectangle, StartPoint.X); 40 Canvas.SetTop(rectangle, StartPoint.Y); 41 MyCanvas.Children.Add(rectangle); 42 43 isMouseDown = true; 44 } 45 46 private void MyCanvas_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) 47 { 48 var R_X = MovePoint.X; 49 var R_Y = MovePoint.Y; 50 var R_H=rectangle.ActualHeight; 51 var R_W=rectangle.ActualWidth; 52 MyRects.Add(new MyRect(R_X,R_Y,R_H,R_W, Brushes.Red, Brushes.Transparent));//追加した 53 MyCanvas.Children.Add(MyRects[MyRects.Count-1]); 54 isMouseDown = false; 55 rectangle.Opacity = 1; 56 } 57 58 private void MyCanvas_MouseMove(object sender, MouseEventArgs e) 59 { 60 if (!isMouseDown) return; 61 62 var point = e.GetPosition(MyCanvas); 63 64 //var leftOffset = point.X % 10;//罫線に合わせる必要はないためコメントアウト 65 //leftOffset = leftOffset < 5 ? -leftOffset : 10 - leftOffset; 66 //var topOffset = point.Y % 10; 67 //topOffset = topOffset < 5 ? -topOffset : 10 - topOffset; 68 69 var leftOffset = point.X; 70 var topOffset = point.Y; 71 72 MovePoint = new Point(point.X + leftOffset, point.Y + topOffset); 73 rectangle.Width = Math.Abs(MovePoint.X - StartPoint.X); 74 rectangle.Height = Math.Abs(MovePoint.Y - StartPoint.Y); 75 76 if (MovePoint.X - StartPoint.X <= 0) 77 { 78 Canvas.SetLeft(rectangle, MovePoint.X); 79 } 80 if (MovePoint.Y - StartPoint.Y <= 0) 81 { 82 Canvas.SetTop(rectangle, MovePoint.Y); 83 } 84 } 85 86 private void MyCanvas_MouseLeave(object sender, MouseEventArgs e) 87 { 88 89 } 90 }
試したこと(6/20 9:30修正)
Canvasコントロールの子要素を動的に増減させたい
https://teratail.com/questions/359699
とりあえず、Rectangleの値を動的に生成したり、
選択したRectangleのサイズ等を取得したいです。
(移動や拡縮は、おいおいやります)
とりあえず勉強の為、別で1つ作りました。
Rect.cs
1 public class MyRect 2 { 3 public double X { get; set; } 4 public double Y { get; set; } 5 public double Width { get; set; } 6 public double Height { get; set; } 7 8 } 9 10 public class RectangleItem : MyRect 11 { 12 public Brush Stroke { get; set; } 13 public Brush Fill { get; set; } 14 } 15 16 17}
xaml.cs
1 2 public MainWindow() 3 { 4 InitializeComponent(); 5 var imageFolder = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "image"); 6 DataContext = new ViewModel(imageFolder); 7 } 8 9 private void MyCanvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) 10 { 11 var point = e.GetPosition(MyCanvas); 12 13 var leftOffset = point.X % 10; 14 leftOffset = leftOffset < 5 ? -leftOffset : 10 - leftOffset; 15 var topOffset = point.Y % 10; 16 topOffset = topOffset < 5 ? -topOffset : 10 - topOffset; 17 18 StartPoint = new Point(point.X + leftOffset, point.Y + topOffset); 19 20 rectangle = new Rectangle 21 { 22 Stroke = Brushes.Black, 23 Fill = Brushes.LightBlue, 24 HorizontalAlignment = HorizontalAlignment.Left, 25 VerticalAlignment = VerticalAlignment.Top, 26 Width = 0, 27 Height = 0, 28 Opacity = 0.3 29 }; 30 31 Canvas.SetLeft(rectangle, StartPoint.X); 32 Canvas.SetTop(rectangle, StartPoint.Y); 33 MyCanvas.Children.Add(rectangle); 34 35 isMouseDown = true; 36 } 37 38 private void MyCanvas_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) 39 { 40 var R_X = MovePoint.X; 41 var R_Y = MovePoint.Y; 42 var R_H=rectangle.ActualHeight; 43 var R_W=rectangle.ActualWidth; 44 MyCanvas.Children.Remove(rectangle); 45 MyRects.Add(new RectangleItem { X = R_X, Y = R_Y, Width =R_W, Height =R_H, Fill = Brushes.Transparent, Stroke=Brushes.Red}); 46 47 48 isMouseDown = false; 49 rectangle.Opacity = 1; 50 }
MainWindow.xaml
1 <Window.Resources> 2 <DataTemplate DataType="{x:Type local:RectangleItem}"> 3 <Rectangle Width="{Binding Width}" Height="{Binding Height}" Fill="{Binding Fill}" Stroke="{Binding Stroke}" /> 4 </DataTemplate> 5 </Window.Resources> 6 <Grid> 7 <ItemsControl ItemsSource="{Binding MyRects}"> 8 <ItemsControl.ItemsPanel> 9 <ItemsPanelTemplate> 10 <Canvas /> 11 </ItemsPanelTemplate> 12 </ItemsControl.ItemsPanel> 13 <ItemsControl.ItemContainerStyle> 14 <Style> 15 <Setter Property="Canvas.Left" Value="{Binding X}" /> 16 <Setter Property="Canvas.Top" Value="{Binding Y}" /> 17 </Style> 18 </ItemsControl.ItemContainerStyle> 19 </ItemsControl> 20 </Grid>
MyRect.cs
1 public class MyRect 2 { 3 public double X { get; set; } 4 public double Y { get; set; } 5 public double Width { get; set; } 6 public double Height { get; set; } 7 8 } 9 10 public class RectangleItem : MyRect 11 { 12 public Brush Stroke { get; set; } = Brushes.Red; 13 public Brush Fill { get; set; } = Brushes.Transparent; 14 }
MyCanvas.Children.Remove(rectangle);で
描画していた四角形を消すところまでは出来ましたが、
Rectangleが動的生成されません。なぜでしょう……?
①ViewModel.csにRectsを追加しなければならないのか?
②MyRectsの値を見るとちゃんと値は入っているものの
Rectangleが自動生成されない
→やはりViewModel.csに追加していないから?
((ViewModel)DataContext).MyRects.Add(new RectangleItem { X = 100, Y = 50, Width = 50, Height = 50 });
LeftButtonup時に上記内容を追加するようにしたら
MyRectsに値は追加されましたが四角形は表示されませんでした。
補足情報(FW/ツールのバージョンなど)
Visualstudio2022 V17.6.3
.NET 6.0 C#

回答4件
あなたの回答
tips
プレビュー