質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.31%
.NET

.NETとは、主に.NET Frameworkと呼ばれるアプリケーションまたは開発環境を指します。CLR(共通言語ランタイム)を搭載し、入力された言語をCIL(共通中間言語)に変換・実行することが可能です。そのため、C#やPythonなど複数の言語を用いることができます。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Q&A

2回答

1435閲覧

WPF DataGridとオブジェクトを連動させたい

AsuAriko

総合スコア0

.NET

.NETとは、主に.NET Frameworkと呼ばれるアプリケーションまたは開発環境を指します。CLR(共通言語ランタイム)を搭載し、入力された言語をCIL(共通中間言語)に変換・実行することが可能です。そのため、C#やPythonなど複数の言語を用いることができます。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

0グッド

0クリップ

投稿2023/09/28 04:42

実現したいこと

①サブウィンドウのDataGridに一覧を表示させる
②選択したDataGridの内容にあわせて、動作させる
(MainWindowsの画像を変更し、同じ画像の内容のものを表示させる)
③MainWindowにあるRectangleは、拡縮移動ができる
(Rectangle等を選択すると、選択した内容のDataGridが選択され、
DataGirdを選択すると、Rectangleにフォーカスがいく)
④SubWindowに「保存」ボタンがあり、それを押すとテキストファイルとして保存できる

①~③の動作イメージです。Excelを利用して作ってます。
イメージ説明
黒い太枠が今選択しているもので、
薄い水色背景は同じ画像のものという意味です。

現在、Rectangle(Button)の表示、拡縮、移動機能は出来ました。
DataGridへのデータ表示もできました。
あとは、ButtonとDataGridの連動、
そしてDataGridで選択を変更した時に画像が違う場合に
画像背景とRectangleの変更の実装です。

前提

WPF 動的生成したRectangleがドラッグで移動できない、Bindingが難しい…
https://teratail.com/questions/j700zzpncph60k
→私には難しくて理解が出来ませんでした。申し訳ありません。

リサイズハンドルをAdornerで実装する
https://como-2.hatenadiary.org/entry/20110428/1303996288
→これを元に、フォーカス後に移動とかも実装しました。

発生している問題・エラーメッセージ

MVVMもそうですが、データの流れが良く分かりません。
一人で作っているため、自分がデータの流れを読めれば良く
速度とかもそこまで気にしていないため、自分で理解できる作成方法が一番だと思いました。

MVVMとかBindingとかあまり理解できていないので色々と間違っているかもしれませんが、データの値が追いやすいものにして、上記②を実現させたいです。
ViewModelを作成し、MainWindowにもDataWindowにも
DataContextに入れる?ことにしました。
MainWindowで□ボタンを押したらDataGridにも追加されるところまでは出来ました。

該当のソースコード

MainWindow.xaml

1<Window x:Class="ImageMapCreate.MainWindow" 2 x:Name="Root" 3 mc:Ignorable="d" 4 Title="MainWindow" Height="630" Width="800"> 5 6 <Window.Resources> 7 <!--リサイズハンドル用のテンプレート定義--> 8 <ControlTemplate TargetType="Thumb" x:Key="ResizeHandleTemplate"> 9 <Ellipse Width="10" Height="10" Margin="-3" 10 Stroke="DimGray" Fill="LightSteelBlue"/> 11 </ControlTemplate> 12 <!--装飾用のテンプレート定義--> 13 <ControlTemplate x:Key="AdornerTemplate"> 14 <Grid> 15 <Thumb Name="MoveThumb" 16 HorizontalAlignment="Center" VerticalAlignment="Center" 17 Template="{StaticResource ResizeHandleTemplate}" 18 DragDelta="ResizeThumb_DragDelta"/> 19 <Thumb Name="ResizeThumb_LT" 20 HorizontalAlignment="Left" VerticalAlignment="Top" 21 Template="{StaticResource ResizeHandleTemplate}" 22 DragDelta="ResizeThumb_DragDelta"/> 23 <Thumb Name="ResizeThumb_RT" 24 HorizontalAlignment="Right" VerticalAlignment="Top" 25 Template="{StaticResource ResizeHandleTemplate}" 26 DragDelta="ResizeThumb_DragDelta"/> 27 <Thumb Name="ResizeThumb_LB" 28 HorizontalAlignment="Left" VerticalAlignment="Bottom" 29 Template="{StaticResource ResizeHandleTemplate}" 30 DragDelta="ResizeThumb_DragDelta"/> 31 <Thumb Name="ResizeThumb_RB" 32 HorizontalAlignment="Right" VerticalAlignment="Bottom" 33 Template="{StaticResource ResizeHandleTemplate}" 34 DragDelta="ResizeThumb_DragDelta"/> 35 </Grid> 36 </ControlTemplate> 37 38 </Window.Resources> 39 <Grid> 40 <StackPanel Orientation="Vertical"> 41 <ToolBar Height="30"> 42 <Button x:Name="Create_rect" Content="□" Click="Create_rect_Click"></Button> 43 </ToolBar> 44 45 <Canvas Name="MyCanvas"> 46 <Image Width="800" Height="600"/> 47 <Button x:Name="ButtonStyleTemp" 48 Width="{Binding Width}" 49 Height="{Binding Height}" 50 Canvas.Left="{Binding X}" 51 Canvas.Top="{Binding Y}" 52 Content="{Binding HintText}" 53 Visibility="Hidden"> 54 <Button.Style> 55 <Style TargetType="Button"> 56 <Style.Triggers> 57 <Trigger Property="IsFocused" Value="True"> 58 <Setter Property="local:AdornedBy.Template" 59 Value="{StaticResource AdornerTemplate}"/> 60 </Trigger> 61 </Style.Triggers> 62 </Style> 63 </Button.Style> 64 </Button> 65 </Canvas > 66 67 </StackPanel> 68 </Grid>

MainWindow.cs

1public partial class MainWindow : Window 2 { 3 private readonly ViewModel vm = new ViewModel(); 4 public MainWindow() 5 { 6 InitializeComponent(); 7 8 DataContext = vm; 9 var window = new DataWindow(); 10 window.DataContext = vm; 11 window.Show(); 12 } 13 14 private void Create_rect_Click(object sender, RoutedEventArgs e) 15 { 16<!--省略--> 17 } 18 19 private void ResizeThumb_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e) 20 { 21 var thumb = sender as Thumb; 22 if (thumb == null) return; 23 var adored = AdornedBy.GetAdornedElementFromTemplateChild(thumb) as FrameworkElement; 24 if (adored == null) return; 25 Debug.WriteLine(adored.Name); 26 27 if (thumb.Name == "MoveThumb") 28 { 29 Canvas.SetLeft(adored, Canvas.GetLeft(adored) + e.HorizontalChange); 30 Canvas.SetTop(adored, Canvas.GetTop(adored) + e.VerticalChange); 31 e.Handled = true; 32 return; 33 } 34 var befo_bottom = Canvas.GetBottom(adored); 35 var befo_right = Canvas.GetRight(adored); 36 var befo_top = Canvas.GetTop(adored); 37 var befo_left = Canvas.GetLeft(adored); 38 var after_left = 0; 39 var after_top = 0; 40 var after_right = 0; 41 var after_bottom = 0; 42 var after_width = 0; 43 var after_height = 0; 44 //移動ではない場合 45 46 if (thumb.Name == "ResizeThumb_LT") 47 { 48 after_left = (int)(Canvas.GetLeft(adored) + e.HorizontalChange); 49 after_top = (int)(Canvas.GetTop(adored) + e.VerticalChange); 50 after_width = (int)(adored.Width - e.HorizontalChange); 51 after_height= (int)(adored.Height - e.VerticalChange); 52 after_right = after_left + after_width; 53 after_bottom = after_top + after_height; 54 if (after_width < 20) return; 55 if (after_height < 20) return; 56 if (after_left > after_right) return; 57 if (after_top > after_bottom) return; 58 adored.Height = after_height; 59 Canvas.SetTop(adored, after_top); 60 adored.Width = after_width; 61 Canvas.SetLeft(adored, after_left); 62 } 63 64 if (thumb.Name == "ResizeThumb_RT") 65 { 66 after_left = (int)(Canvas.GetLeft(adored));//LEFTは変わらない 67 after_top = (int)(Canvas.GetTop(adored) + e.VerticalChange); 68 after_width = (int)(adored.Width + e.HorizontalChange); 69 after_height = (int)(adored.Height - e.VerticalChange); 70 after_right = after_left + after_width; 71 after_bottom = after_top + after_height; 72 if (after_width < 20) return; 73 if (after_height < 20) return; 74 if (after_left > after_right) return; 75 if (after_top > after_bottom) return; 76 adored.Height = after_height; 77 Canvas.SetTop(adored, after_top); 78 adored.Width = after_width; 79 Canvas.SetLeft(adored, after_left); 80 } 81 82 if (thumb.Name == "ResizeThumb_LB") 83 { 84 after_left = (int)(Canvas.GetLeft(adored) + e.HorizontalChange); 85 after_top = (int)(Canvas.GetTop(adored));//TOPは変わらない 86 after_width = (int)(adored.Width - e.HorizontalChange); 87 after_height = (int)(adored.Height + e.VerticalChange); 88 after_right = after_left + after_width; 89 after_bottom = after_top + after_height; 90 if (after_width < 20) return; 91 if (after_height < 20) return; 92 if (after_left > after_right) return; 93 if (after_top > after_bottom) return; 94 adored.Height = after_height; 95 Canvas.SetTop(adored, after_top); 96 adored.Width = after_width; 97 Canvas.SetLeft(adored, after_left); 98 } 99 if (thumb.Name == "ResizeThumb_RB") 100 { 101 after_left = (int)(Canvas.GetLeft(adored));//LEFTは変わらない 102 after_top = (int)(Canvas.GetTop(adored));//Topも変わらない 103 after_width = (int)(adored.Width + e.HorizontalChange); 104 after_height = (int)(adored.Height + e.VerticalChange); 105 after_right = after_left + after_width; 106 after_bottom = after_top + after_height; 107 if (after_width < 20) return; 108 if (after_height < 20) return; 109 if (after_left > after_right) return; 110 if (after_top > after_bottom) return; 111 adored.Height = after_height; 112 Canvas.SetTop(adored, after_top); 113 adored.Width = after_width; 114 Canvas.SetLeft(adored, after_left); 115 } 116 } 117 118 } 119

DataWindow.xaml

1 <DockPanel> 2 <ToolBar Height="30" DockPanel.Dock="Top" FontWeight="Bold" > 3 <Button x:Name="ReadFileB" Content="ファイル読み込み" Click="ReadFile_Click" Background="#FFFFBCDE" /> 4 <Button x:Name="WriteFileB" Content="ファイル書き込み" Click="WriteFile_Click" Background="#FFAFFFD5" /> 5 <Button x:Name="AddB" Content="追加" Click="Add_Click"/> 6 </ToolBar> 7 <!--<rg:ReoGridControl x:Name = "ReoGrid" Height="300" />--> 8 <DataGrid x:Name="MyGrid" ItemsSource="{Binding Items, UpdateSourceTrigger=PropertyChanged}" CanUserSortColumns="False" SelectionChanged="DataGrid_SelectionChanged" AutoGenerateColumns="False" CanUserReorderColumns="False" CanUserAddRows="False" > 9 <DataGrid.Columns> 10 <DataGridTextColumn Header="番号" Binding="{Binding Num}" IsReadOnly="True" /> 11 <DataGridTextColumn Header="タイトル" Binding="{Binding Title}" /> 12 <DataGridTextColumn Header="画像ファイル名" Binding="{Binding PicName}" IsReadOnly="True" /> 13 <DataGridTextColumn Header="X" Binding="{Binding X" /> 14 <DataGridTextColumn Header="Y" Binding="{Binding Y}" /> 15 <DataGridTextColumn Header="W" Binding="{Binding Width}" /> 16 <DataGridTextColumn Header="H" Binding="{Binding Height}" /> 17 <DataGridTextColumn Header="ヒント" Binding="{Binding HintText}" /> 18 <DataGridTextColumn Header="線の色" Binding="{Binding BordColor}" /> 19 <DataGridTextColumn Header="塗り色" Binding="{Binding FillColor}" /> 20 <DataGridTextColumn Header="次リンク" Binding="{Binding NextLink}" IsReadOnly="True"/> 21 <DataGridTemplateColumn Header="追加" x:Name="Add"> 22 <DataGridTemplateColumn.CellTemplate> 23 <DataTemplate> 24 <Button Click="Add_Click" Content="+" /> 25 </DataTemplate> 26 </DataGridTemplateColumn.CellTemplate> 27 </DataGridTemplateColumn> 28 <DataGridTemplateColumn Header="削除" x:Name="Del"> 29 <DataGridTemplateColumn.CellTemplate> 30 <DataTemplate> 31 <Button Click="Del_Click" Content="-" /> 32 </DataTemplate> 33 </DataGridTemplateColumn.CellTemplate> 34 </DataGridTemplateColumn> 35 </DataGrid.Columns> 36 </DataGrid> 37 </DockPanel>

DataWindow.xaml.cs

1 private void Add_Click(object sender, RoutedEventArgs e) 2 { 3 ViewModel.Items.Add(new Item{ Num = 1, Title ="タイトル"});//とりあえず 4 } 5 6 private void Del_Click(object sender, RoutedEventArgs e) 7 { 8 var dataGrid = sender as DataGrid; 9 var cellInfos = MyGrid.SelectedCells; 10 if (cellInfos.Count == 0) 11 { 12 return; 13 } 14 var cellInfo = cellInfos[0]; 15 var item = cellInfo.Item; 16 var rowIndex = MyGrid.Items.IndexOf(item); 17 ViewModel.Items.RemoveAt(rowIndex); 18 19 }

試したこと

adoredという所で、「Name」と指定すれば情報が取得できたので、
今動かしているものの情報は取れそうな気がします。
それをどうやってDataGridに連動させるかが良く分かりません。
回答、アドバイスのほど、よろしくお願いいたします。

補足情報(FW/ツールのバージョンなど)

WPF C#
.NET 6.0
CommunityToolkit.Mvvm 8.2.1

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

TN8001

2023/09/28 10:11

[C# と VB.NET の質問掲示板 - C# WPFで、親子両方で共通で使うデータを作りたい](http://bbs.wankuma.com/index.cgi?mode=all&namber=102422) こちらの質問と同一人物ですよね? 同一内容というわけではないため「マルチポスト」というわけではありませんが、マナーとして関連するものはリンク等提示してください。 マナーという意味ではあちらのスレッドを、続けるなりクローズするなりすべきと思いますが^^;
TN8001

2023/09/28 10:11

> ②選択したDataGridの内容にあわせて、動作させる > (MainWindowsの画像を変更し、同じ画像の内容のものを表示させる) 「同じ画像の内容のもの」というのは赤い枠(Rectangle)のことですか? CanvasにはButton1個しかありませんがどうするつもりですか? > 黒い太枠が今選択しているもので、 > 薄い水色背景は同じ画像のものという意味です。 DataGridでいうと「黒い太枠」はカレント?(フォーカス?)行(セル)で、「薄い水色背景」が選択行に見えます。 例えばCtrl+クリック等をすると、「薄い水色背景」で【ない】行に「黒い太枠」が付くことがあります。 それとも例えば1番をクリックすると自動で1,2が選択され、5番をクリックすると自動で3~6が選択されるという意味ですか?(これは地味に厄介かもしれません。グループ化とかのほうが楽そう) > 現在、Rectangle(Button)の表示、拡縮、移動機能は出来ました。 > DataGridへのデータ表示もできました。 > あとは、ButtonとDataGridの連動、 Buttonひとつでいいなら↓のようにするだけで簡単に連動します。 <DataGrid IsSynchronizedWithCurrentItem="True" <Button x:Name="ButtonStyleTemp" Canvas.Left="{Binding Items/X}" Canvas.Top="{Binding Items/Y}" Width="{Binding Items/Width}" Height="{Binding Items/Height}" Content="{Binding Items/HintText}"> [方法: 階層データでマスター詳細パターンを使用する - WPF .NET Framework | Microsoft Learn](https://learn.microsoft.com/ja-jp/dotnet/desktop/wpf/data/how-to-use-the-master-detail-pattern-with-hierarchical-data) ただしButtonひとつです。そうではなく複数赤い枠を出すのなら、ListBoxベースにすべきです(そしてそれは上の参考リンク回答です) > そしてDataGridで選択を変更した時に画像が違う場合に > 画像背景とRectangleの変更の実装です。 背景画像に関しては上記の通り↓とするだけです。 <Image Width="800" Height="600" Source="{Binding Items/PicName}" /> > →私には難しくて理解が出来ませんでした。申し訳ありません。 > →これを元に、フォーカス後に移動とかも実装しました。 CoMoさんの記事は理解できたということですか?(わたしは未だにMeasure・Arrangeあたり理解できていませんが^^; 要素一つと複数とでは当然難易度は変わります。 特にItemsControlやListBoxはカスタマイズ性が高い分、(いじろうとすると)難易度もそれなりに高いです。 わたしも過去何度も同系統の質問に回答し、やっと決定版といえる内容(ビヘイビア版)になったと自負しているだけに「難しい」の一言でスルーされるのは大変残念です。 どの辺が「難しい」ですか? 完全版をGitHubにあげていますが、動かしていただけていますか? > MVVMとかBindingとかあまり理解できていないので色々と間違っているかもしれませんが、データの値が追いやすいものにして、上記②を実現させたいです。 例えばC#コードでCanvasにButtonを動的に追加削除することで実現できるかもしれません。 追いやすいといえば追いやすいですが、おそらくバインドやStyleもコードで設定しないと動かないでしょう(特に確認してません) > ViewModelを作成し、MainWindowにもDataWindowにも > DataContextに入れる?ことにしました。 はい。これは正しい解決法です^^
hqf00342

2023/09/29 03:56

悩んでいるのは、Canvas上の図形(Rectangle)とDataGridに表示しているデータを結び付ける方法ということでしょうか? また、DataGridに表示している「Items」はどのような定義ですか?
TN8001

2023/10/01 10:19

回答する気があるから不明点を聞いてるのに、だんまり君はどういう了見なんだろう?ほんとわからん。 まああちらをクローズしてない時点で予想はしてたけどorz
guest

回答2

0

→私には難しくて理解が出来ませんでした。

ビヘイビアにしているってことは、「詳細は知らなくってもいい」ってことです。
使い方だけ把握していれば、後は良しなにやってくれます^^
xamlだけでも結構難しいですが、もともとListBoxに図形を出すこと自体がそこそこ難しいので...(でも割と定型パターンです)

xml:MainWindow.xaml

1<Window 2 x:Class="Q29545c8iv6n7wd.MainWindow" 3 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 4 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 5 xmlns:i="http://schemas.microsoft.com/xaml/behaviors" 6 xmlns:local="clr-namespace:Q29545c8iv6n7wd" 7 Title="MainWindow" 8 Width="800" 9 Height="630"> 10 <Window.Resources> 11 <ControlTemplate x:Key="ResizeAdornerTemplate"> 12 <ControlTemplate.Resources> 13 <!-- Thumbのテンプレート Resourcesにキーなし登録で↓のThumbに暗黙的に適用 --> 14 <Style TargetType="Thumb"> 15 <Setter Property="Template"> 16 <Setter.Value> 17 <ControlTemplate> 18 <Rectangle MinWidth="10" MinHeight="10" Margin="-5" Fill="Transparent" /> 19 <!-- 半透明色をつけると構造が分かりやすい --> 20 <!--<Rectangle MinWidth="20" MinHeight="20" Margin="-10" Fill="#330000FF" />--> 21 </ControlTemplate> 22 </Setter.Value> 23 </Setter> 24 </Style> 25 </ControlTemplate.Resources> 26 <Grid> 27 <!-- 移動用 --> 28 <Thumb Cursor="SizeAll" /> 29 <!-- 辺リサイズ用 --> 30 <Thumb HorizontalAlignment="Left" Cursor="SizeWE" /> 31 <Thumb HorizontalAlignment="Right" Cursor="SizeWE" /> 32 <Thumb VerticalAlignment="Top" Cursor="SizeNS" /> 33 <Thumb VerticalAlignment="Bottom" Cursor="SizeNS" /> 34 <!-- 角リサイズ用 --> 35 <Thumb HorizontalAlignment="Left" VerticalAlignment="Top" Cursor="SizeNWSE" /> 36 <Thumb HorizontalAlignment="Right" VerticalAlignment="Top" Cursor="SizeNESW" /> 37 <Thumb HorizontalAlignment="Left" VerticalAlignment="Bottom" Cursor="SizeNESW" /> 38 <Thumb HorizontalAlignment="Right" VerticalAlignment="Bottom" Cursor="SizeNWSE" /> 39 </Grid> 40 </ControlTemplate> 41 </Window.Resources> 42 43 <DockPanel> 44 <ToolBar DockPanel.Dock="Top"> 45 <Button Command="{Binding AddCommand}" Content="" /> 46 </ToolBar> 47 48 <Grid> 49 <Image Source="{Binding Items/PicName}" /> 50 51 <ListBox Background="{x:Null}" ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem}"> 52 <!-- 配置にCanvasを使用 --> 53 <ListBox.ItemsPanel> 54 <ItemsPanelTemplate> 55 <Canvas /> 56 </ItemsPanelTemplate> 57 </ListBox.ItemsPanel> 58 59 <!-- 個々のItemをどう表示するか --> 60 <ListBox.ItemTemplate> 61 <DataTemplate DataType="{x:Type local:Item}"> 62 <Border Width="{Binding Width, Mode=TwoWay}" Height="{Binding Height, Mode=TwoWay}" Background="Transparent" BorderBrush="Red" BorderThickness="2"> 63 <i:Interaction.Behaviors> 64 <!-- 動かしたいもの(Border)にアタッチするといい感じにやってくれる^^ --> 65 <local:ResizeBehavior AdornerTemplate="{StaticResource ResizeAdornerTemplate}" /> 66 </i:Interaction.Behaviors> 67 <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Binding Num}" /> 68 </Border> 69 </DataTemplate> 70 </ListBox.ItemTemplate> 71 72 <!-- X・YはListBoxItemにバインドが必要 --> 73 <ListBox.ItemContainerStyle> 74 <Style TargetType="ListBoxItem"> 75 <Setter Property="Canvas.Left" Value="{Binding X, Mode=TwoWay}" /> 76 <Setter Property="Canvas.Top" Value="{Binding Y, Mode=TwoWay}" /> 77 <Setter Property="Template"> 78 <Setter.Value> 79 <ControlTemplate TargetType="ListBoxItem"> 80 <Grid> 81 <!-- 選択中を表す点線 --> 82 <Rectangle x:Name="rectangle" Margin="-4" Stroke="Black" StrokeDashArray="4 4" Visibility="Collapsed" /> 83 <!-- この中にBorderが入ってくる --> 84 <ContentPresenter /> 85 </Grid> 86 <ControlTemplate.Triggers> 87 <!-- 選択された時だけ点線表示 --> 88 <Trigger Property="IsSelected" Value="True"> 89 <Setter TargetName="rectangle" Property="Visibility" Value="Visible" /> 90 </Trigger> 91 </ControlTemplate.Triggers> 92 </ControlTemplate> 93 </Setter.Value> 94 </Setter> 95 <Style.Triggers> 96 <!-- 同じ画像Itemのみ表示 フィルター機能でやるのが真っ当だが、元コードを流用して手抜き^^; --> 97 <!-- IsSelectedはResizeBehaviorと相性が悪いので、素直に専用プロパティ(IsRectVisible)を作る --> 98 <DataTrigger Binding="{Binding IsRectVisible}" Value="False"> 99 <Setter Property="Visibility" Value="Collapsed" /> 100 </DataTrigger> 101 </Style.Triggers> 102 </Style> 103 </ListBox.ItemContainerStyle> 104 </ListBox> 105 </Grid> 106 </DockPanel> 107</Window>

cs:MainWindow.xaml.cs

1using System.Windows; 2 3namespace Q29545c8iv6n7wd; 4 5public partial class MainWindow : Window 6{ 7 private readonly ViewModel vm = new(); 8 public MainWindow() 9 { 10 InitializeComponent(); 11 DataContext = vm; 12 new DataWindow { DataContext = vm, }.Show(); 13 } 14}

xml:DataWindow.xaml

1<Window 2 x:Class="Q29545c8iv6n7wd.DataWindow" 3 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 4 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 5 x:Name="Root" 6 Title="DataWindow" 7 Width="600" 8 Height="630"> 9 <DockPanel> 10 <ToolBar DockPanel.Dock="Top"> 11 <Button Content="ファイル読み込み" /> 12 <Button Content="ファイル書き込み" /> 13 <Button Command="{Binding AddCommand}" Content="追加" /> 14 </ToolBar> 15 16 <DataGrid AutoGenerateColumns="False" CanUserAddRows="False" IsSynchronizedWithCurrentItem="True" ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem}"> 17 <DataGrid.Resources> 18 <!-- ↓の都合上非アクティブ選択色が見えるとややこしいので、アクティブ選択色で上書き --> 19 <SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightBrushKey}" Color="{x:Static SystemColors.HighlightColor}" /> 20 <SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightTextBrushKey}" Color="{x:Static SystemColors.HighlightTextColor}" /> 21 <Style TargetType="{x:Type DataGridRow}"> 22 <Style.Triggers> 23 <!-- 同じ画像Itemが選択されるよう行に選択色をつける(そう見せるだけ実際は複数選択していない) --> 24 <DataTrigger Binding="{Binding IsRectVisible}" Value="True"> 25 <Setter Property="Background" Value="{StaticResource {x:Static SystemColors.HighlightBrushKey}}" /> 26 <Setter Property="Foreground" Value="{StaticResource {x:Static SystemColors.HighlightTextBrushKey}}" /> 27 </DataTrigger> 28 </Style.Triggers> 29 </Style> 30 </DataGrid.Resources> 31 32 <DataGrid.Columns> 33 <DataGridTextColumn Binding="{Binding Num}" Header="番号" IsReadOnly="True" /> 34 <DataGridTextColumn Binding="{Binding Title}" Header="タイトル" /> 35 <DataGridTextColumn Width="*" Binding="{Binding PicName}" Header="画像ファイル名" IsReadOnly="True" /> 36 <DataGridTextColumn Binding="{Binding X}" Header="X" /> 37 <DataGridTextColumn Binding="{Binding Y}" Header="Y" /> 38 <DataGridTextColumn Binding="{Binding Width}" Header="W" /> 39 <DataGridTextColumn Binding="{Binding Height}" Header="H" /> 40 <DataGridTemplateColumn Header="削除"> 41 <DataGridTemplateColumn.CellTemplate> 42 <DataTemplate> 43 <!-- この時点でDataContextは個々のItemのため、DelCommandはElementName等で取ってくる必要あり --> 44 <!-- CommandParameterでItem自体({Binding})を渡せば削除が簡単 --> 45 <Button Command="{Binding DataContext.DelCommand, ElementName=Root}" CommandParameter="{Binding}" Content="-" /> 46 </DataTemplate> 47 </DataGridTemplateColumn.CellTemplate> 48 </DataGridTemplateColumn> 49 </DataGrid.Columns> 50 </DataGrid> 51 </DockPanel> 52</Window>

cs:ViewModel.cs

1using System.Collections.ObjectModel; 2using CommunityToolkit.Mvvm.ComponentModel; 3using CommunityToolkit.Mvvm.Input; 4 5namespace Q29545c8iv6n7wd; 6 7public partial class ViewModel : ObservableObject 8{ 9 public ObservableCollection<Item> Items { get; } 10 11 // [ObservableProperty 属性 - .NET Community Toolkit | Microsoft Learn](https://learn.microsoft.com/ja-jp/dotnet/communitytoolkit/mvvm/generators/observableproperty) 12 [ObservableProperty] private Item? _SelectedItem; // 選択中Item 13 14 // 変更時のコードの実行 - .NET Community Toolkit | Microsoft Learn](https://learn.microsoft.com/ja-jp/dotnet/communitytoolkit/mvvm/generators/observableproperty#running-code-upon-changes) 15 partial void OnSelectedItemChanged(Item? value) 16 { 17 foreach (var item in Items) 18 { 19 if (value == null) item.IsRectVisible = false; // 選択解除時はすべてfalse 20 else item.IsRectVisible = item.PicName == value.PicName; 21 } 22 } 23 24 public ViewModel() 25 { 26 var a = "https://www.gravatar.com/avatar/d0384607accbaad6adaa964b59cd8ddb?d=identicon"; 27 var b = "https://teratail-v2.storage.googleapis.com/uploads/avatars/u13/132786/KnkDDC5A_thumbnail.jpg"; 28 29 Items = new() 30 { 31 new() { Title = "1つ目だよ", PicName = a, Width = 50, Height = 50, }, 32 new() { Title = "2つ目だよ", PicName = a, X = 200, Y = 200, Width = 200, Height = 200, }, 33 new() { PicName = b, }, 34 new() { PicName = b, X = 300, Y = 300, }, 35 new() { Title = "5番目", PicName = b, X = 100, Y = 100, Width = 30, Height = 30, }, 36 new() { PicName = b, X = 130, Y = 130, }, 37 new() { Width = 50, Height = 50, }, 38 }; 39 } 40 41 // [RelayCommand 属性 - .NET Community Toolkit | Microsoft Learn](https://learn.microsoft.com/ja-jp/dotnet/communitytoolkit/mvvm/generators/relaycommand) 42 [RelayCommand] private void Add() => Items.Add(SelectedItem = new() { IsRectVisible = true, }); 43 [RelayCommand] private void Del(Item item) => Items.Remove(item); 44} 45 46public partial class Item : ObservableObject 47{ 48 private static int no; // 雑いw 49 50 public int Num { get; } 51 [ObservableProperty] private string? _Title; 52 public string? PicName { get; init; } 53 [ObservableProperty] private int _X; 54 [ObservableProperty] private int _Y; 55 [ObservableProperty] private int _Width = 100; 56 [ObservableProperty] private int _Height = 100; 57 [ObservableProperty] private bool _IsRectVisible; // 選択中Itemと同じ画像Itemかどうか 58 59 public Item() => (Num, Title) = (++no, $"{no}だよ"); 60}

NuGet Gallery | CommunityToolkit.Mvvm 8.2.1
NuGet Gallery | Microsoft.Xaml.Behaviors.Wpf 1.1.39

アプリ動画

投稿2023/10/01 10:18

TN8001

総合スコア10022

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

TN8001

2023/10/01 10:18

返事がないのでシカトしてもよかったのですが、せっかく用意したしビヘイビアの確認も兼ねて回答しておきます。 Thumbのカスタマイズもやりたかったのですが、文字数的に無理でしたw どのThumbかの判定にAlignmentを使っている都合上、質問画像のような〇だとひと工夫必要になります。 そもそも〇以外でリサイズできないUIの意味が分からないので、Thumbとは別個にEllipseでも出せばいいんじゃないですかね。
guest

0

質問ポイントが複数にわたるので分けて記載しますが、
コードは書ききれないので質問コードをベースにしたサンプルを置きます。

https://github.com/hqf00342/Wpf_teratail_29545c8iv6n7wd

(質問内の他サイト様コードを丸ごと引用のため、しばらくしたら削除します。)


データの見通しをよくしたい

全データを管理するデータセット(以降、モデルと言います)を1つ用意し、各UI部品はそのモデルデータを参照します。
UIを更新したら必ずそのモデルのデータも更新することで整合性を保ちます。各UIコントロールはモデルデータの変更を検知して自分に反映するようにします。
UI同士でデータ連携しようとせず、必ずモデルを介することで見通し良くします。(その分パフォーマンスは悪くなります)
モデルデータ変更時のUI更新はWPFの場合はBindingを使うのが一般的です。

csharp

1//モデルデータ 2internal class OriginData 3{ 4 public static ObservableCollection<Item> OriginItems = new ObservableCollection<Item>(); 5} 6 7public partial class Item : ObservableObject 8{ 9 [ObservableProperty] private double x; 10 [ObservableProperty] private double y; 11 ....省略 12}
DataGridの複数データをCanvas側でどう管理、連携するか

DataGrid同様にCanvas側にもコレクションを管理する機能が必要です。
簡単なケースならItemsControlをCanvas化して利用、凝ったことをしたければ自分で実装します。2つのコントロールが同じモデル(コレクション)を参照することで連携します。
ItemsControlを使うとXAMLは長いですが、C#コードはすっきりします。

xml

1<ItemsControl Width="800" Height="600" ItemsSource="{Binding Items}"> 2 3 <ItemsControl.ItemsPanel> 4 <ItemsPanelTemplate> 5 <Canvas /> 6 </ItemsPanelTemplate> 7 </ItemsControl.ItemsPanel> 8 9 <ItemsControl.ItemTemplate> 10 <DataTemplate> 11 <Button Content="{Binding HintText}" 12 Width="{Binding Width}" Height="{Binding Height}"> 13 <Button.Style> 14 <Style TargetType="Button"> 15 <Style.Triggers> 16 <Trigger Property="IsFocused" Value="True"> 17 <Setter Property="local:AdornedBy.Template" 18 Value="{StaticResource AdornerTemplate}" /> 19 </Trigger> 20 </Style.Triggers> 21 </Style> 22 </Button.Style> 23 </Button> 24 </DataTemplate> 25 </ItemsControl.ItemTemplate> 26 27 <ItemsControl.ItemContainerStyle> 28 <Style TargetType="ContentPresenter"> 29 <Setter Property="Canvas.Left" Value="{Binding X,Mode=TwoWay}" /> 30 <Setter Property="Canvas.Top" Value="{Binding Y,Mode=TwoWay}" /> 31 </Style> 32 </ItemsControl.ItemContainerStyle> 33</ItemsControl>
AdornerからDataGridまで反映させる方法

ResizeThumb_DragDelta()でadored変数に対象のButtonは抽出できてます。
このButtonとモデルのデータを何らかの方法で結び付け、データ更新することで別コントロール(DataGrid)に反映させます。
MVVM利用ならButton.DataContextプロパティに自動で入ってます。MVVM未利用ならばButton.Tagプロパティ等に対象データを入れたり、実際の位置から計算して特定する手もあります。

csharp

1private void ResizeThumb_DragDelta(object sender, DragDeltaEventArgs e) 2{ 3 var thumb = sender as Thumb; 4 if (thumb == null) return; 5 var button = AdornedBy.GetAdornedElementFromTemplateChild(thumb) as Button; 6 if (button == null) return; 7 //バインディングされているアイテムを取得 8 Item item = button.DataContext as Item;

対象のモデルデータが手に入れば、それを更新すれば全UIコントロールに反映されます。

選択状態の連携

別のWindow間であればモデルやViewModelに選択アイテム用プロパティを1つ用意します。
今回は2つのWindowで同じViewModelを参照しているようなので、ViewModelで共有します。

csharp

1public partial class ViewModel : ObservableObject 2{ 3 ...4 /// <summary>選択アイテム</summary> 5 [ObservableProperty] private Item selectedItem;

MVVMの思想的には1つのViewModelを複数のViewで共有しないのですが、一人開発ならMVVMをあまり気にせず、プログラムを完成させることを目指しましょう。

投稿2023/09/30 20:12

編集2023/10/01 03:59
hqf00342

総合スコア394

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.31%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問