お世話になります。
調べたのですが、分からないため教えてください。
実現したいこと
以前質問させていただいた2つを組み合わせたものにしようとしています。
Rectangleの質問【1】のデータを主軸とし、
画像選択サブウィンドウのデータ【2】を追加しようとしています。
組み合わせても問題なく動作するようにしたいです。
【1】
WPF 動的生成したRectangleがドラッグで移動できない、Bindingが難しい…
https://teratail.com/questions/j700zzpncph60k
→ソースが変わる前のものを利用しています。
【2】
WPF C# ImageSourceを利用しているからか、画像がロックされてしまう
https://teratail.com/questions/t6uox4f1iujybm
試したこと
ViewModelを1つにまとめました。
Itemsという同じ名称のものは、「RectItems」「PicItems」としました。
MainWindow.xaml
1 <Grid> 2 <Grid.RowDefinitions> 3 <RowDefinition Height="30" /> 4 <RowDefinition Height="600"/> 5 <RowDefinition Height="*"/> 6 </Grid.RowDefinitions> 7 <ToolBar Grid.Row="0" VerticalAlignment="Top" Height="30"> 8 <Button Content="画像選択" Width="128" Height="32" Click="Button_Click"/> 9 <RadioButton x:Name="DefaultButton" Width="32" Height="32" 10 Content="?" IsChecked="True" /> 11 <RadioButton x:Name="RectButton" Width="32" Height="32"> 12 <Rectangle Width="24" Height="16" Stroke="Black"/> 13 </RadioButton> 14 </ToolBar> 15 16 <!-- <Image Grid.Row="1" MinWidth="600" MinHeight="600" Height="600" MaxWidth="800" MaxHeight="600" Width="800" Source="{Binding SelectedPic.FilePath, Converter={StaticResource ImageConverter}}" StretchDirection="DownOnly" HorizontalAlignment="Left" VerticalAlignment="Top" />--> 17 <local:MyCanvas MinHeight="600" MaxHeight="600" Height="600" MinWidth="800" Width="800" MaxWidth="800" Grid.Row="1" RectItems="{Binding RectInfoCollection}" SelectRect="{Binding SelectRect, Mode=TwoWay}" > 18 </local:MyCanvas> 19 <local:MyDataGrid Grid.Row="2" DataContext="{Binding }"/> 20 21 </Grid>
MainWindow.cs
1 public partial class MainWindow : Window 2 { 3 public ViewModel vm ; 4 public MainWindow() 5 { 6 InitializeComponent(); 7 var imageFolder = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "image"); 8 vm = new ViewModel(imageFolder); 9 this.DataContext = vm; 10 } 11 private void Button_Click(object sender, RoutedEventArgs e) 12 => new SubWindow((ViewModel)DataContext).ShowDialog(); 13 14 private void Window_Loaded(object sender, RoutedEventArgs e) 15 { 16 vm.RectInfoCollection.Add(new RectInfo("1", 10, 10, 100, 100, "Red", "")); 17 vm.RectInfoCollection.Add(new RectInfo("2", 100, 100, 200, 200, "Blue", "")); 18 19 } 20} 21
ViewModel.cs
1public partial class ViewModel : BindableBase 2{ 3 private RectInfo? _SelectedRect; 4 public RectInfo? SelectedRect { get => _SelectedRect; set => SetProperty(ref _SelectedRect, value); } 5 6 public ObservableCollection<Item> PicItems { get; } = new(); 7 8 private Item? _SelectPic; 9 public Item? SelectPic { get => _SelectPic; set => SetProperty(ref _SelectPic, value); } 10 11 private readonly string folder; 12 public ViewModel(string folder) 13 { 14 this.folder = folder; 15 Directory.CreateDirectory(folder); 16 ImportFiles(Directory.EnumerateFiles(folder, "*.jpg", SearchOption.TopDirectoryOnly)); 17 } 18 19 [RelayCommand] 20 private void Apply(Item? item) => SelectPic = item; 21 22 public void ImportFiles(IEnumerable<string> paths) 23 { 24 foreach (var path in paths) PicItems.Add(new(path)); 25 } 26 27 public void AddItem(string path, Func<bool> isOverwrite) 28 { 29 var fileName = System.IO.Path.GetFileNameWithoutExtension(path); 30 var outPath = System.IO.Path.Combine(folder, $"{fileName}.jpg"); 31 32 if (File.Exists(outPath)) 33 { 34 if (!isOverwrite()) return; 35 PicItems.Remove(PicItems.FirstOrDefault(x => x.FilePath == outPath)!); 36 } 37 38 using (var fsin = new FileStream(path, FileMode.Open, FileAccess.ReadWrite)) 39 using (var fsout = new FileStream(outPath, FileMode.Create, FileAccess.Write)) 40 { 41 var f = BitmapFrame.Create(fsin, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnDemand); 42 var meta = f.Metadata.Clone() as BitmapMetadata ?? new BitmapMetadata("jpg"); 43 var enc = new JpegBitmapEncoder(); 44 enc.Frames.Add(BitmapFrame.Create(f, f.Thumbnail, meta, f.ColorContexts)); 45 enc.Save(fsout); 46 } 47 48 PicItems.Add(new(outPath)); 49 } 50}
発生している問題・エラーメッセージ
- Rectangleが表示されない(SelectRectもRe
- Canvasの裏に画像を表示させようとImageを追加したが、それも表示されない(SelectPicのデータはあり)
MyCanvas.cs
1 public MyCanvas() 2 { 3 InitializeComponent(); 4 } 5 6 private System.Windows.Point _dragOffset; 7 private System.Windows.Shapes.Rectangle? _dragRectangle; 8 public RectInfo SelectRect 9 { 10 get { return (RectInfo)GetValue(SelectRectProperty); } 11 set { SetValue(SelectRectProperty, value); } 12 } 13 14 public static readonly DependencyProperty SelectRectProperty = 15 DependencyProperty.Register("SelectRect", typeof(RectInfo), typeof(MyCanvas), new PropertyMetadata(null, SelectRect_Changed)); 16 17 private static void SelectRect_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e) 18 { 19 (d as MyCanvas)?.SelectRectChanged(e.OldValue, e.NewValue); 20 } 21 22 private void SelectRectChanged(object oldValue, object newValue) 23 { 24 if (oldValue is RectInfo o) 25 { 26 var target = FindRectangle(o); 27 if (target != null) 28 { 29 target.StrokeDashArray = null; 30 } 31 } 32 if (newValue is RectInfo n) 33 { 34 var target = FindRectangle(n); 35 if (target != null) 36 { 37 target.StrokeDashArray = new DoubleCollection() { 2 }; 38 } 39 } 40 } 41 42 public ObservableCollection<RectInfo> RectItems 43 { 44 get { return (ObservableCollection<RectInfo>)GetValue(RectItemsProperty); } 45 set { SetValue(RectItemsProperty, value); } 46 } 47 48 public static readonly DependencyProperty RectItemsProperty = 49 DependencyProperty.Register("RectItems", typeof(ObservableCollection<RectInfo>), typeof(MyCanvas), new PropertyMetadata(null, RectItemsChangedCallback)); 50 51 private static void RectItemsChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e) 52 { 53 (d as MyCanvas)?.RegisterCollectionChanged(); 54 } 55 56 private void RegisterCollectionChanged() 57 { 58 RectItems.CollectionChanged += RectItems_CollectionChanged; 59 } 60 61 private void RectItems_CollectionChanged(object? sender, NotifyCollectionChangedEventArgs e) 62 { 63 switch (e.Action) 64 { 65 case NotifyCollectionChangedAction.Add: 66 if (e.NewItems != null) 67 { 68 foreach (RectInfo mp in e.NewItems) 69 { 70 AddRectangle(mp); 71 mp.PropertyChanged += RectInfo_PropertyChanged; 72 } 73 } 74 break; 75 76 case NotifyCollectionChangedAction.Remove: 77 if (e.OldItems != null) 78 { 79 foreach (RectInfo info in e.OldItems) 80 { 81 var target = FindRectangle(info); 82 if (target != null) 83 { 84 canvas2.Children.Remove(target); 85 info.PropertyChanged -= RectInfo_PropertyChanged; 86 } 87 } 88 } 89 break; 90 91 default: 92 break; 93 } 94 } 95 96 private System.Windows.Shapes.Rectangle? FindRectangle(RectInfo info) 97 { 98 if (info == null) return null; 99 return canvas2.Children.OfType<System.Windows.Shapes.Rectangle>().FirstOrDefault(i => info == (RectInfo)i.Tag); 100 } 101 102 internal void AddRectangle(RectInfo info) 103 { 104 var r = new System.Windows.Shapes.Rectangle 105 { 106 Width = 20, 107 Height = 20, 108 Stroke=Brushes.Black, 109 StrokeThickness=5, 110 ToolTip = info.Name, 111 Tag = info 112 }; 113 114 r.Width = info.Width; 115 r.Height = info.Height; 116 117 try 118 { 119 var brush = (SolidColorBrush)new BrushConverter().ConvertFromString(info.BorderColor); 120 r.Stroke = brush; 121 } 122 catch 123 { 124 r.Stroke = Brushes.Transparent; 125 } 126 127 try { 128 var brush = (SolidColorBrush)new BrushConverter().ConvertFromString(info.FillColor); 129 r.Fill = brush; 130 } 131 catch 132 { 133 r.Fill = Brushes.Transparent; 134 } 135 136 //イベント追加 137 r.MouseDown += DragStart; 138 r.MouseUp += (o, e) => { _dragRectangle = null; r.ReleaseMouseCapture(); }; 139 r.MouseMove += MoveRectangle; 140 141 //パネルに追加 142 canvas2.Children.Add(r); 143 Canvas.SetLeft(r, info.X); 144 Canvas.SetTop(r, info.Y); 145 }
###分かったこと
画面上にボタンを置き
「vm.RectInfoCollection.Add(new RectInfo("3", 10, 10, 100, 100, "Red", ""));」としてみたところ、四角形が描画されました。
起動時に作成したデータでは四角形が出来ず、DataGridのみに表示されますが、ボタンで実行すると四角形描画とDataGridへの追加もどちらもできるようです。
画面上に置いたボタンで追加できるのであれば、
Binding自体は問題ない気がします。
補足情報(FW/ツールのバージョンなど)
Visualstudio2022 V17.6.3
.NET 6.0 C#

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