回答編集履歴
1
コード追記
test
CHANGED
@@ -1,16 +1,18 @@
|
|
1
1
|
|
2
|
-
質問ポイントが複数にわたる
|
2
|
+
質問ポイントが複数にわたるので分けて記載しますが、
|
3
|
-
コードは書ききれないのでサンプルを
|
3
|
+
コードは書ききれないので質問コードをベースにしたサンプルを置きます。
|
4
4
|
|
5
5
|
https://github.com/hqf00342/Wpf_teratail_29545c8iv6n7wd
|
6
6
|
|
7
|
-
(
|
7
|
+
(質問内の他サイト様コードを丸ごと引用のため、しばらくしたら削除します。)
|
8
8
|
|
9
9
|
----
|
10
10
|
|
11
11
|
##### データの見通しをよくしたい
|
12
|
-
全データを管理するデータセット(以降、モデルと言います)を1つ用意し、各UI部品はそのモデルデータを参照します。
|
12
|
+
全データを管理するデータセット(以降、モデルと言います)を1つ用意し、各UI部品はそのモデルデータを参照します。
|
13
|
-
|
13
|
+
UIを更新したら必ずそのモデルのデータも更新することで整合性を保ちます。各UIコントロールはモデルデータの変更を検知して自分に反映するようにします。
|
14
|
+
UI同士でデータ連携しようとせず、必ずモデルを介することで見通し良くします。(その分パフォーマンスは悪くなります)
|
15
|
+
モデルデータ変更時のUI更新はWPFの場合はBindingを使うのが一般的です。
|
14
16
|
```csharp
|
15
17
|
//モデルデータ
|
16
18
|
internal class OriginData
|
@@ -26,12 +28,63 @@
|
|
26
28
|
}
|
27
29
|
```
|
28
30
|
##### DataGridの複数データをCanvas側でどう管理、連携するか
|
31
|
+
|
32
|
+
DataGrid同様にCanvas側にもコレクションを管理する機能が必要です。
|
29
|
-
|
33
|
+
簡単なケースなら`ItemsControl`をCanvas化して利用、凝ったことをしたければ自分で実装します。2つのコントロールが同じモデル(コレクション)を参照することで連携します。
|
34
|
+
`ItemsControl`を使うとXAMLは長いですが、C#コードはすっきりします。
|
35
|
+
|
36
|
+
```xml
|
37
|
+
<ItemsControl Width="800" Height="600" ItemsSource="{Binding Items}">
|
38
|
+
|
39
|
+
<ItemsControl.ItemsPanel>
|
40
|
+
<ItemsPanelTemplate>
|
41
|
+
<Canvas />
|
42
|
+
</ItemsPanelTemplate>
|
43
|
+
</ItemsControl.ItemsPanel>
|
44
|
+
|
45
|
+
<ItemsControl.ItemTemplate>
|
46
|
+
<DataTemplate>
|
47
|
+
<Button Content="{Binding HintText}"
|
48
|
+
Width="{Binding Width}" Height="{Binding Height}">
|
49
|
+
<Button.Style>
|
50
|
+
<Style TargetType="Button">
|
51
|
+
<Style.Triggers>
|
52
|
+
<Trigger Property="IsFocused" Value="True">
|
53
|
+
<Setter Property="local:AdornedBy.Template"
|
54
|
+
Value="{StaticResource AdornerTemplate}" />
|
55
|
+
</Trigger>
|
56
|
+
</Style.Triggers>
|
57
|
+
</Style>
|
58
|
+
</Button.Style>
|
59
|
+
</Button>
|
60
|
+
</DataTemplate>
|
61
|
+
</ItemsControl.ItemTemplate>
|
62
|
+
|
63
|
+
<ItemsControl.ItemContainerStyle>
|
64
|
+
<Style TargetType="ContentPresenter">
|
65
|
+
<Setter Property="Canvas.Left" Value="{Binding X,Mode=TwoWay}" />
|
66
|
+
<Setter Property="Canvas.Top" Value="{Binding Y,Mode=TwoWay}" />
|
67
|
+
</Style>
|
68
|
+
</ItemsControl.ItemContainerStyle>
|
69
|
+
</ItemsControl>
|
70
|
+
```
|
30
71
|
|
31
72
|
##### AdornerからDataGridまで反映させる方法
|
32
73
|
|
33
|
-
ResizeThumb_DragDelta()で`adored`に対象のButtonは抽出できて
|
34
|
-
|
74
|
+
ResizeThumb_DragDelta()で`adored`変数に対象のButtonは抽出できてます。
|
75
|
+
このButtonとモデルのデータを何らかの方法で結び付け、データ更新することで別コントロール(DataGrid)に反映させます。
|
76
|
+
MVVM利用なら`Button.DataContext`プロパティに自動で入ってます。MVVM未利用ならば`Button.Tag`プロパティ等に対象データを入れたり、実際の位置から計算して特定する手もあります。
|
77
|
+
```csharp
|
78
|
+
private void ResizeThumb_DragDelta(object sender, DragDeltaEventArgs e)
|
79
|
+
{
|
80
|
+
var thumb = sender as Thumb;
|
81
|
+
if (thumb == null) return;
|
82
|
+
var button = AdornedBy.GetAdornedElementFromTemplateChild(thumb) as Button;
|
83
|
+
if (button == null) return;
|
84
|
+
//バインディングされているアイテムを取得
|
85
|
+
Item item = button.DataContext as Item;
|
86
|
+
```
|
87
|
+
対象のモデルデータが手に入れば、それを更新すれば全UIコントロールに反映されます。
|
35
88
|
##### 選択状態の連携
|
36
89
|
|
37
90
|
別のWindow間であればモデルやViewModelに選択アイテム用プロパティを1つ用意します。
|
@@ -39,11 +92,10 @@
|
|
39
92
|
```csharp
|
40
93
|
public partial class ViewModel : ObservableObject
|
41
94
|
{
|
42
|
-
|
95
|
+
...略
|
43
|
-
public ObservableCollection<Item> Items => OriginData.OriginItems;
|
44
|
-
|
45
96
|
/// <summary>選択アイテム</summary>
|
46
97
|
[ObservableProperty] private Item selectedItem;
|
47
98
|
```
|
99
|
+
|
48
100
|
MVVMの思想的には1つのViewModelを複数のViewで共有しないのですが、一人開発ならMVVMをあまり気にせず、プログラムを完成させることを目指しましょう。
|
49
101
|
|