回答編集履歴
1
見直しキャンペーン中
answer
CHANGED
@@ -1,222 +1,215 @@
|
|
1
|
-
tarokoさんのここ1月弱の質問は、すべて関連しているんですよね?
|
2
|
-
`Rectangle`の移動リサイズまで考えると、だいぶ先が長そうですね^^;
|
3
|
-
|
4
|
-
> ・他から参照できるよう、NowData.csクラスに値を入れたい
|
5
|
-
|
6
|
-
データのもと(csv等から読む予定?)をどうやって表示するかを、MVVM的にやった場合の例です。
|
7
|
-
|
8
|
-
> ・全部のxamlから参照できるDictionaryは作成できるのか
|
9
|
-
|
10
|
-
追加順を保持したいとのことなので、`OrderedDictionary`にしました(非ジェネリックなのでほんとにイヤなのですが^^;
|
11
|
-
[OrderedDictionary クラス (System.Collections.Specialized) | Microsoft Docs](https://docs.microsoft.com/ja-jp/dotnet/api/system.collections.specialized.ordereddictionary)
|
12
|
-
|
13
|
-
回答コードは3つのウィンドウがあります。
|
14
|
-
* メインウィンドウ
|
15
|
-
`DataGrid`と`Canvas`。編集・追加と可視化(マウスでは動きませんよ?^^;
|
16
|
-
* `DetailView`ウィンドウ
|
17
|
-
1件の詳細画面。編集も同期する。
|
18
|
-
* `DefaultSetting`ウィンドウ
|
19
|
-
追加時デフォルト色の設定。`Properties.Settings`を直接読み書きする。
|
20
|
-
|
21
|
-
基本的には親玉(`MainWindow`)がデータ(`ViewModel`)を保持し、欲しい人(`DetailView`)に参照を渡します。
|
22
|
-
場合によっては`DefaultSetting`のように、
|
23
|
-
|
24
|
-
`INotifyPropertyChanged`を実装しているクラス(`Rectan`と`Properties.Settings`)のプロパティは、変更が即Viewに反映されています(この気持ちのよさのため、長いプロパティを書いたのです^^
|
25
|
-
|
26
|
-
|
27
|
-
すごい見にくくて申し訳ありませんが、1万字に圧縮するためです。
|
28
|
-
App.xaml
|
29
|
-
|
30
|
-
<Application
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
<
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
```
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
<
|
45
|
-
|
46
|
-
<Grid.ColumnDefinitions>
|
47
|
-
|
48
|
-
<
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
<
|
55
|
-
|
56
|
-
|
57
|
-
<Style>
|
58
|
-
|
59
|
-
|
60
|
-
<
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
<
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
<DataGridTextColumn Binding="{Binding
|
71
|
-
<
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
<
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
<
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
<
|
97
|
-
|
98
|
-
<
|
99
|
-
<
|
100
|
-
<
|
101
|
-
<
|
102
|
-
<
|
103
|
-
<
|
104
|
-
<
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
<
|
111
|
-
</
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
public
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
```
|
216
|
-

|
217
|
-
|
218
|
-

|
219
|
-
|
220
|
-
---
|
221
|
-
|
1
|
+
tarokoさんのここ1月弱の質問は、すべて関連しているんですよね?
|
2
|
+
`Rectangle`の移動リサイズまで考えると、だいぶ先が長そうですね^^;
|
3
|
+
|
4
|
+
> ・他から参照できるよう、NowData.csクラスに値を入れたい
|
5
|
+
|
6
|
+
データのもと(csv等から読む予定?)をどうやって表示するかを、MVVM的にやった場合の例です。
|
7
|
+
|
8
|
+
> ・全部のxamlから参照できるDictionaryは作成できるのか
|
9
|
+
|
10
|
+
追加順を保持したいとのことなので、`OrderedDictionary`にしました(非ジェネリックなのでほんとにイヤなのですが^^;
|
11
|
+
[OrderedDictionary クラス (System.Collections.Specialized) | Microsoft Docs](https://docs.microsoft.com/ja-jp/dotnet/api/system.collections.specialized.ordereddictionary)
|
12
|
+
|
13
|
+
回答コードは3つのウィンドウがあります。
|
14
|
+
* メインウィンドウ
|
15
|
+
`DataGrid`と`Canvas`。編集・追加と可視化(マウスでは動きませんよ?^^;
|
16
|
+
* `DetailView`ウィンドウ
|
17
|
+
1件の詳細画面。編集も同期する。
|
18
|
+
* `DefaultSetting`ウィンドウ
|
19
|
+
追加時デフォルト色の設定。`Properties.Settings`を直接読み書きする。
|
20
|
+
|
21
|
+
基本的には親玉(`MainWindow`)がデータ(`ViewModel`)を保持し、欲しい人(`DetailView`)に参照を渡します。
|
22
|
+
場合によっては`DefaultSetting`のように、staticで(`Properties.Settings`)アクセスしてもいいでしょう。
|
23
|
+
|
24
|
+
`INotifyPropertyChanged`を実装しているクラス(`Rectan`と`Properties.Settings`)のプロパティは、変更が即Viewに反映されています(この気持ちのよさのため、長いプロパティを書いたのです^^
|
25
|
+
|
26
|
+
|
27
|
+
すごい見にくくて申し訳ありませんが、1万字に圧縮するためです。
|
28
|
+
```xml:App.xaml
|
29
|
+
<Application x:Class="Questions345835.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" ShutdownMode="OnMainWindowClose" StartupUri="MainWindow.xaml">
|
30
|
+
<Application.Resources>
|
31
|
+
<DataTemplate x:Key="template">
|
32
|
+
<DockPanel>
|
33
|
+
<Ellipse Width="16" Height="16" Fill="{Binding Value}" />
|
34
|
+
<TextBlock Margin="5,0" VerticalAlignment="Center" Text="{Binding Key}" />
|
35
|
+
</DockPanel>
|
36
|
+
</DataTemplate>
|
37
|
+
</Application.Resources>
|
38
|
+
</Application>
|
39
|
+
```
|
40
|
+
```xml:MainWindow.xaml
|
41
|
+
<Window x:Class="Questions345835.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:l="clr-namespace:Questions345835" Width="800" Height="600" Left="200" Top="200">
|
42
|
+
<Grid>
|
43
|
+
<Grid.ColumnDefinitions>
|
44
|
+
<ColumnDefinition />
|
45
|
+
<ColumnDefinition />
|
46
|
+
</Grid.ColumnDefinitions>
|
47
|
+
<ItemsControl ItemsSource="{Binding Rectans}">
|
48
|
+
<ItemsControl.ItemsPanel>
|
49
|
+
<ItemsPanelTemplate>
|
50
|
+
<Canvas Background="WhiteSmoke" />
|
51
|
+
</ItemsPanelTemplate>
|
52
|
+
</ItemsControl.ItemsPanel>
|
53
|
+
<ItemsControl.ItemContainerStyle>
|
54
|
+
<Style>
|
55
|
+
<Setter Property="Canvas.Top" Value="{Binding Top}" />
|
56
|
+
<Setter Property="Canvas.Left" Value="{Binding Left}" />
|
57
|
+
</Style>
|
58
|
+
</ItemsControl.ItemContainerStyle>
|
59
|
+
<ItemsControl.ItemTemplate>
|
60
|
+
<DataTemplate DataType="{x:Type l:Rectan}">
|
61
|
+
<Rectangle Width="{Binding Width}" Height="{Binding Height}" Fill="{Binding Fill}" Stroke="{Binding Border}" StrokeThickness="5" />
|
62
|
+
</DataTemplate>
|
63
|
+
</ItemsControl.ItemTemplate>
|
64
|
+
</ItemsControl>
|
65
|
+
<DataGrid Grid.Column="1" AutoGenerateColumns="False" ItemsSource="{Binding Rectans}" SelectedItem="{Binding Current, Mode=TwoWay, TargetNullValue={x:Static CollectionView.NewItemPlaceholder}}" SelectionMode="Single">
|
66
|
+
<DataGrid.Columns>
|
67
|
+
<DataGridTextColumn Binding="{Binding Left}" Header="Left" />
|
68
|
+
<DataGridTextColumn Binding="{Binding Top}" Header="Top" />
|
69
|
+
<DataGridTextColumn Binding="{Binding Width}" Header="Width" />
|
70
|
+
<DataGridTextColumn Binding="{Binding Height}" Header="Height" />
|
71
|
+
<DataGridTemplateColumn Header="Border">
|
72
|
+
<DataGridTemplateColumn.CellTemplate>
|
73
|
+
<DataTemplate>
|
74
|
+
<ComboBox ItemTemplate="{StaticResource template}" ItemsSource="{x:Static l:Choices.Colors}" SelectedValue="{Binding Border, UpdateSourceTrigger=PropertyChanged}" SelectedValuePath="Value" />
|
75
|
+
</DataTemplate>
|
76
|
+
</DataGridTemplateColumn.CellTemplate>
|
77
|
+
</DataGridTemplateColumn>
|
78
|
+
<DataGridTemplateColumn Header="Fill">
|
79
|
+
<DataGridTemplateColumn.CellTemplate>
|
80
|
+
<DataTemplate>
|
81
|
+
<ComboBox ItemTemplate="{StaticResource template}" ItemsSource="{x:Static l:Choices.Colors}" SelectedValue="{Binding Fill, UpdateSourceTrigger=PropertyChanged}" SelectedValuePath="Value" />
|
82
|
+
</DataTemplate>
|
83
|
+
</DataGridTemplateColumn.CellTemplate>
|
84
|
+
</DataGridTemplateColumn>
|
85
|
+
</DataGrid.Columns>
|
86
|
+
</DataGrid>
|
87
|
+
</Grid>
|
88
|
+
</Window>
|
89
|
+
```
|
90
|
+
```xml:DetailView.xaml
|
91
|
+
<Window x:Class="Questions345835.DetailView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:l="clr-namespace:Questions345835" Title="DetailView" Width="300" Background="WhiteSmoke" Left="1000" ResizeMode="NoResize" SizeToContent="Height" Top="450">
|
92
|
+
<StackPanel Margin="5" DataContext="{Binding Current}">
|
93
|
+
<TextBlock Text="Left" />
|
94
|
+
<TextBox Text="{Binding Left, UpdateSourceTrigger=PropertyChanged}" />
|
95
|
+
<TextBlock Text="Top" />
|
96
|
+
<TextBox Text="{Binding Top, UpdateSourceTrigger=PropertyChanged}" />
|
97
|
+
<TextBlock Text="Width" />
|
98
|
+
<TextBox Text="{Binding Width, UpdateSourceTrigger=PropertyChanged}" />
|
99
|
+
<TextBlock Text="Height" />
|
100
|
+
<TextBox Text="{Binding Height, UpdateSourceTrigger=PropertyChanged}" />
|
101
|
+
<TextBlock Text="Border" />
|
102
|
+
<ComboBox ItemTemplate="{StaticResource template}" ItemsSource="{x:Static l:Choices.Colors}" SelectedValue="{Binding Border, UpdateSourceTrigger=PropertyChanged}" SelectedValuePath="Value" />
|
103
|
+
<TextBlock Text="Fill" />
|
104
|
+
<ComboBox ItemTemplate="{StaticResource template}" ItemsSource="{x:Static l:Choices.Colors}" SelectedValue="{Binding Fill, UpdateSourceTrigger=PropertyChanged}" SelectedValuePath="Value" />
|
105
|
+
</StackPanel>
|
106
|
+
</Window>
|
107
|
+
```
|
108
|
+
```xml:DefaultSetting.xaml
|
109
|
+
<Window x:Class="Questions345835.DefaultSetting" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:l="clr-namespace:Questions345835" xmlns:p="clr-namespace:Questions345835.Properties" Title="DefaultSetting" Width="300" Background="WhiteSmoke" Left="1000" ResizeMode="NoResize" SizeToContent="Height" Top="200">
|
110
|
+
<StackPanel Margin="5">
|
111
|
+
<Border Height="40" Margin="50,10" Background="{Binding SelectedItem.Value, ElementName=fill}" BorderBrush="{Binding SelectedItem.Value, ElementName=border}" BorderThickness="5" />
|
112
|
+
<TextBlock Text="Border" />
|
113
|
+
<ComboBox Name="border" ItemTemplate="{StaticResource template}" ItemsSource="{x:Static l:Choices.Colors}" SelectedValue="{Binding DefaultBorderColor, Source={x:Static p:Settings.Default}}" SelectedValuePath="Key" />
|
114
|
+
<TextBlock Text="Fill" />
|
115
|
+
<ComboBox Name="fill" ItemTemplate="{StaticResource template}" ItemsSource="{x:Static l:Choices.Colors}" SelectedValue="{Binding DefaultFillColor, Source={x:Static p:Settings.Default}}" SelectedValuePath="Key" />
|
116
|
+
</StackPanel>
|
117
|
+
</Window>
|
118
|
+
```
|
119
|
+
|
120
|
+
```cs
|
121
|
+
using CommunityToolkit.Mvvm.ComponentModel;
|
122
|
+
using System.Collections.ObjectModel;
|
123
|
+
using System.Collections.Specialized;
|
124
|
+
using System.ComponentModel;
|
125
|
+
using System.Windows;
|
126
|
+
using System.Windows.Media;
|
127
|
+
|
128
|
+
namespace Questions345835
|
129
|
+
{
|
130
|
+
// コンボボックスの選択肢クラス
|
131
|
+
public static class Choices
|
132
|
+
{
|
133
|
+
// ValueTupleはフィールドなのでバインドできず、Tupleは共変?じゃない
|
134
|
+
// OrderedDictionaryは非ジェネリックで悩ましい
|
135
|
+
public static OrderedDictionary Colors { get; } =
|
136
|
+
new OrderedDictionary
|
137
|
+
{
|
138
|
+
{ "赤", Brushes.Red },
|
139
|
+
{ "青", Brushes.Blue },
|
140
|
+
{ "緑", Brushes.Green },
|
141
|
+
{ "白", Brushes.White },
|
142
|
+
{ "黒", Brushes.Black },
|
143
|
+
{ "透明", Brushes.Transparent },
|
144
|
+
};
|
145
|
+
}
|
146
|
+
|
147
|
+
// Rectangleの元データになるクラス 値の変更があるのでINotifyPropertyChangedを実装
|
148
|
+
public class Rectan : ObservableObject
|
149
|
+
{
|
150
|
+
// なんだか長いですが変更通知のため仕方がありません。定型コードと割り切ってください^^;
|
151
|
+
public double Left { get => _Left; set => SetProperty(ref _Left, value); }
|
152
|
+
private double _Left;
|
153
|
+
public double Top { get => _Top; set => SetProperty(ref _Top, value); }
|
154
|
+
private double _Top;
|
155
|
+
public double Width { get => _Width; set => SetProperty(ref _Width, value); }
|
156
|
+
private double _Width;
|
157
|
+
public double Height { get => _Height; set => SetProperty(ref _Height, value); }
|
158
|
+
private double _Height;
|
159
|
+
public Brush Border { get => _Border; set => SetProperty(ref _Border, value); }
|
160
|
+
private Brush _Border;
|
161
|
+
public Brush Fill { get => _Fill; set => SetProperty(ref _Fill, value); }
|
162
|
+
private Brush _Fill;
|
163
|
+
|
164
|
+
public Rectan() // 引数なしコンストラクタがないとDataGridで追加ができない
|
165
|
+
{
|
166
|
+
// とりあえず初期表示される値
|
167
|
+
(Left, Top, Width, Height) = (100, 100, 100, 100);
|
168
|
+
// デフォルトで入れたいデータ(Settings.settings)は直読み
|
169
|
+
Border = (Brush)Choices.Colors[Properties.Settings.Default.DefaultBorderColor];
|
170
|
+
Fill = (Brush)Choices.Colors[Properties.Settings.Default.DefaultFillColor];
|
171
|
+
}
|
172
|
+
}
|
173
|
+
|
174
|
+
public class ViewModel : ObservableObject
|
175
|
+
{
|
176
|
+
// 全データ
|
177
|
+
public ObservableCollection<Rectan> Rectans { get; } = new ObservableCollection<Rectan>();
|
178
|
+
|
179
|
+
// 今参照しているデータ(全データの中の1行分のデータ)
|
180
|
+
public Rectan Current { get => _Current; set => SetProperty(ref _Current, value); }
|
181
|
+
private Rectan _Current;
|
182
|
+
|
183
|
+
public ViewModel()
|
184
|
+
{
|
185
|
+
// ファイルから読んでRectansに追加する等。とりあえず1件あったことにする
|
186
|
+
Rectans.Add(new Rectan());
|
187
|
+
}
|
188
|
+
}
|
189
|
+
|
190
|
+
public partial class MainWindow : Window
|
191
|
+
{
|
192
|
+
// 場合によってはpublic staticで見せてもまあいいでしょう^^;
|
193
|
+
//public static ViewModel VM { get; }
|
194
|
+
|
195
|
+
public MainWindow()
|
196
|
+
{
|
197
|
+
InitializeComponent();
|
198
|
+
var vm = new ViewModel(); // すべてのデータのもと newは1回だけ
|
199
|
+
DataContext = vm;
|
200
|
+
|
201
|
+
new DefaultSetting().Show();
|
202
|
+
new DetailView { DataContext = vm, }.Show(); // ほしい人がいたら渡す
|
203
|
+
}
|
204
|
+
|
205
|
+
protected override void OnClosing(CancelEventArgs e) => Properties.Settings.Default.Save();
|
206
|
+
}
|
207
|
+
}
|
208
|
+
```
|
209
|
+

|
210
|
+
|
211
|
+

|
212
|
+
|
213
|
+
---
|
214
|
+
|
222
215
|
実は`MouseDragElementBehavior`も試していたのですが、動的追加は未考慮(動かないわけではないがいろいろおかしい)のようでした。。。
|