Форум программистов, компьютерный форум, киберфорум
C#: WPF, UWP и Silverlight
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.85/39: Рейтинг темы: голосов - 39, средняя оценка - 4.85
 Аватар для ShmelVG
171 / 106 / 51
Регистрация: 27.11.2015
Сообщений: 1,269

Склейщик фото (создание MVVM приложения)

29.04.2019, 16:36. Показов 9175. Ответов 162
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Тема создана как продолжение тем:
Привязать данные к кнопке System.Windows.Data Error: 40
Открыть 2 картинки, переместить, записать координаты используя команду с параметрами
ScrollViewer по вертикали и горизонтали
После выбора файла в диалоговом окне, разместить изображение из файла в canvas
Подключить класс Bitmap

Элд Хасп, я хотел бы после загрузки первого фото, поворачивать её и перемещать, в специальной графе будут отображаться начальные координаты первого фото (левого верхнего угла), и чтоб при загрузки они всегда были бы в верхнем левом углу, потом загружаю второе фото(в специальном месте отображаются координаты 2-ого фото левого верхнего угла), хотел бы так же поворачивать (сейчас после загрузки второго фото поворачиваются 2 картинки, а не вторая), и в специальном месте отображать смещение второго фото по сравнению с первым (так же, по левому верхнему углу). Я не очень понял на счет размеров, я хотел бы чтобы фото отображались во всю величину, но я не буду знать какого фото будут размера. Сейчас приложение ведет себя очень странно, копки стали действительно активны, спасибо! Но когда я пытаюсь их сдвинуть, значение меняется в Text="{Binding Offset}", только не обычно, влево/право - целые числа, а вверх/вниз меняются, сотые этого числа, при этом картинки сами не двигаются, ни первая, ни вторая...

Добавлено через 2 минуты
Элд Хасп, когда запускаю приложение, кнопка вверх и влево не активны, они становятся активны если кликнуть вправо/вниз

Добавлено через 1 минуту
Элд Хасп, задав жестко размер картинке, она деформируется
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
29.04.2019, 16:36
Ответы с готовыми решениями:

Структура WPF приложения на MVVM
Здравствуйте. Разрабатываю приложение на WPF. Использую шаблон MVVM. В представлении контент сгруппирован по вкладкам TabControl. ...

Пример реализации WPF+MVVM приложения
Тема из цикла https://www.cyberforum.ru/wpf-silverlight/thread2384523.html Пример решения ТЗ по теме...

Паттерн MVVM или как писать приложения на WPF
Собтвенно вопрос в заголовке. По-скольку WPF поддерживает привязку различным образом наверно это нужно как-то использовать, а не просто как...

162
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16164 / 11284 / 2891
Регистрация: 21.04.2018
Сообщений: 33,169
Записей в блоге: 2
02.05.2019, 22:40
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от ShmelVG Посмотреть сообщение
- ругался, что пытались из дабл в бул преобразовать, исправил св-во на бул в модели
Свойство ImageModify.IsSelected по типу должно быть bool

Добавлено через 1 минуту
Цитата Сообщение от ShmelVG Посмотреть сообщение
Потом "Повернуть", всего в этом блоке 8 кнопок,
А...
Тогда понятно.
Да, так нормальный дизайн будет.
0
 Аватар для ShmelVG
171 / 106 / 51
Регистрация: 27.11.2015
Сообщений: 1,269
02.05.2019, 22:41  [ТС]
Элд Хасп,
Цитата Сообщение от Элд Хасп Посмотреть сообщение
а к TextBox напрямую
..ээмм, у меня сейчас нет текстбоксов))

Я пока не переделывал view, то сейчас она выглядит так:
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
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
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
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
<Window x:Class="PhotoGluer.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:PhotoGluer.ViewModels"
        mc:Ignorable="d"
        Title="PhotoGluer" Height="800" Width="1200">
 
 
    <Grid>
 
        <Border 
            BorderBrush="Gray"
            BorderThickness="7">
 
            <Grid>
 
                <Grid.ColumnDefinitions>
                    <ColumnDefinition></ColumnDefinition>
                    <ColumnDefinition Width="0.3*"></ColumnDefinition>
                </Grid.ColumnDefinitions>
 
                <Grid Grid.Column="0">
 
                    <Border 
                        Grid.Row="0"
                        BorderBrush="Black"
                        BorderThickness="3"
                        Grid.Column="0"
                        Margin="5">
 
                        <ScrollViewer
                            HorizontalScrollBarVisibility="Auto"
                            VerticalScrollBarVisibility="Auto">
 
                            <StackPanel>
                                <Canvas 
                                    Grid.Column="0"
                                    Width="{Binding SizeCanvas.Width}" 
                                    Height="{Binding SizeCanvas.Height}">
 
                                    <Image x:Name="ImageCam1" 
                                           Source="{Binding FirstImage}"  
                                           Width="{Binding SizeSecondImage.Width}" 
                                           Height="{Binding SizeSecondImage.Height}"
                                           Canvas.Left="{Binding Offset.X}" 
                                           Canvas.Top="{Binding Offset.Y}"
                                           Stretch="None">
 
                                        <Image.LayoutTransform>
                                            <TransformGroup>
                                                <ScaleTransform/>
                                                <SkewTransform/>
                                                <RotateTransform Angle="{Binding Angle}"/>
                                                <TranslateTransform/>
                                            </TransformGroup>
                                        </Image.LayoutTransform>
                                    </Image>
 
                                    <Image x:Name="ImageCam2" 
                                           Source="{Binding SecondImage}" 
                                           RenderTransformOrigin="0.5,0.5" 
                                           Width="{Binding SizeSecondImage.Width}" 
                                           Height="{Binding SizeSecondImage.Height}" 
                                           Canvas.Left="{Binding Offset.X}" 
                                           Canvas.Top="{Binding Offset.Y}"
                                           Stretch="None">
 
                                        <Image.LayoutTransform>
                                            <TransformGroup>
                                                <ScaleTransform/>
                                                <SkewTransform/>
                                                <RotateTransform Angle="{Binding Angle}"/>
                                                <TranslateTransform/>
                                            </TransformGroup>
                                        </Image.LayoutTransform>
                                    </Image>
 
                                </Canvas>
 
                            </StackPanel>
 
                        </ScrollViewer>
 
                    </Border>
 
                </Grid>
 
                <Grid Grid.Column="1">
 
                    <Grid.RowDefinitions>
                        <RowDefinition></RowDefinition>
                        <RowDefinition></RowDefinition>
                        <RowDefinition></RowDefinition>
                    </Grid.RowDefinitions>
 
                    <Grid Grid.Row="0">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition></ColumnDefinition>
                            <ColumnDefinition></ColumnDefinition>
                        </Grid.ColumnDefinitions>
 
                        <Grid.RowDefinitions>
                            <RowDefinition Height="0.5*"></RowDefinition>
                            <RowDefinition Height="0.5*"></RowDefinition>
                            <RowDefinition></RowDefinition>
                            <RowDefinition></RowDefinition>
                            <RowDefinition></RowDefinition>
                        </Grid.RowDefinitions>
 
                        
                        <TextBlock  
                                    Grid.ColumnSpan="2"
                                    Grid.Row="1" 
                                    HorizontalAlignment="Center" 
                                    VerticalAlignment="Center" 
                                    Text="Смещение X,Y" 
                                    FontSize="18"/>
 
                        <Button  
                                    Grid.Column="0"
                                    Grid.Row="2" 
                                    HorizontalAlignment="Center" 
                                    VerticalAlignment="Center" 
                                    Content="Фото 1"
                                    Padding="10 5"
                                    FontSize="18"/>
 
                        <Button 
                                    Grid.Column="0" 
                                    Grid.Row="3" 
                                    HorizontalAlignment="Center" 
                                    VerticalAlignment="Center" 
                                    Content="Фото 2"
                                    Padding="10 5"
                                    FontSize="18"/>
 
                        <TextBlock 
                                    Grid.Column="1" 
                                    Grid.Row="2" 
                                    Height="40" 
                                    FontSize="24" 
                                    VerticalAlignment="Center"                     
                                    HorizontalAlignment="Center"
                                    Width="130"/>
 
                        <TextBlock 
                                    Grid.Column="1" 
                                    Grid.Row="3" 
                                    Height="40" 
                                    FontSize="24" 
                                    VerticalAlignment="Center"                     
                                    HorizontalAlignment="Left"
                                    Width="130"/>
 
                        <TextBlock 
                                    Grid.Column="0" 
                                    Grid.Row="4" 
                                    HorizontalAlignment="Center" 
                                    VerticalAlignment="Center" 
                                    Text="Смещение:" 
                                    FontSize="18"/>
 
                        <TextBlock 
                                    Grid.Column="1" 
                                    Grid.Row="4" 
                                    Height="40" 
                                    FontSize="24" 
                                    VerticalAlignment="Center"
                                    HorizontalAlignment="Left"
                                    Width="130" />
                    </Grid>
                    <Grid Grid.Row="1">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition></ColumnDefinition>
                            <ColumnDefinition></ColumnDefinition>
                        </Grid.ColumnDefinitions>
 
                        <Grid.RowDefinitions>
                            <RowDefinition></RowDefinition>
                            <RowDefinition></RowDefinition>
                            <RowDefinition></RowDefinition>
                            <RowDefinition></RowDefinition>
                            <RowDefinition></RowDefinition>
                            <RowDefinition></RowDefinition>
                        </Grid.RowDefinitions>
 
                        <TextBlock 
                                Grid.ColumnSpan="2" 
                                Grid.Row="0" 
                                TextWrapping="Wrap" 
                                Text="Повернуть" 
                                VerticalAlignment="Center" 
                                HorizontalAlignment="Center"
                                FontSize="18"/>
 
                        <Button 
                                Grid.Column="0"
                                Grid.Row="1" 
                                HorizontalAlignment="Center"
                                VerticalAlignment="Center" 
                                Content="left 1"
                                FontSize="18"/>
 
                        <Button 
                                Grid.Column="0"
                                Grid.Row="2" 
                                HorizontalAlignment="Center"
                                VerticalAlignment="Center" 
                                Content="left 10"
                                FontSize="18"/>
                        <Button 
                                Grid.Column="0"
                                Grid.Row="3" 
                                HorizontalAlignment="Center"
                                VerticalAlignment="Center" 
                                Content="left 45"
                                FontSize="18"/>
 
                        <Button 
                                Grid.Column="0"
                                Grid.Row="4" 
                                HorizontalAlignment="Center"
                                VerticalAlignment="Center" 
                                Content="left 90"
                                FontSize="18"/>
 
                        <Button 
                                Grid.Column="1"
                                Grid.Row="1" 
                                HorizontalAlignment="Center"
                                VerticalAlignment="Center" 
                                Content="right 1"
                                FontSize="18"/>
 
                        <Button 
                                Grid.Column="1"
                                Grid.Row="2" 
                                HorizontalAlignment="Center"
                                VerticalAlignment="Center" 
                                Content="right 10"
                                FontSize="18"/>
 
                        <Button 
                                Grid.Column="1"
                                Grid.Row="3" 
                                HorizontalAlignment="Center"
                                VerticalAlignment="Center" 
                                Content="right 45"
                                FontSize="18"/>
 
                        <Button 
                                Grid.Column="1"
                                Grid.Row="4" 
                                HorizontalAlignment="Center"
                                VerticalAlignment="Center" 
                                Content="right 90"
                                FontSize="18"/>
 
                    </Grid>
 
                    <Grid Grid.Row="2">
 
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition></ColumnDefinition>
                            <ColumnDefinition></ColumnDefinition>
                            <ColumnDefinition></ColumnDefinition>
                        </Grid.ColumnDefinitions>
 
                        <Grid.RowDefinitions>
                            <RowDefinition></RowDefinition>
                            <RowDefinition></RowDefinition>
                            <RowDefinition></RowDefinition>
                        </Grid.RowDefinitions>
 
                        <Button 
                                    Grid.Column="1" 
                                    Grid.Row="0" 
                                    Content="Вверх" 
                                    FontWeight="Bold" 
                                    FontSize="16" 
                                    Margin="2"
                                    BorderThickness="2"
                                    Command="{Binding MoveCommand}"
                                    CommandParameter="Up"/>
 
                        <Button 
                                    Grid.Column="0" 
                                    Grid.Row="1" 
                                    Content="Влево" 
                                    FontWeight="Bold" 
                                    FontSize="16" 
                                    Margin="2"
                                    BorderThickness="2"
                                    Command="{Binding MoveCommand}"
                                    CommandParameter="Left"/>
 
                        <Button 
                                    Grid.Column="2" 
                                    Grid.Row="1" 
                                    Content="Вправо" 
                                    FontWeight="Bold" 
                                    Margin="2"
                                    FontSize="16" 
                                    BorderThickness="2"
                                    Command="{Binding MoveCommand}"
                                    CommandParameter="Rigth"/>
 
                        <Button 
                                    Grid.Column="1" 
                                    Grid.Row="2" 
                                    Content="Вниз" 
                                    FontWeight="Bold" 
                                    Margin="2"
                                    FontSize="16" 
                                    BorderThickness="2"
                                    Command="{Binding MoveCommand}"
                                    CommandParameter="Down"/>
 
                    </Grid>
 
                </Grid>
 
            </Grid>
 
        </Border>
 
    </Grid>
 
</Window>
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16164 / 11284 / 2891
Регистрация: 21.04.2018
Сообщений: 33,169
Записей в блоге: 2
02.05.2019, 22:44
Вроде VM почти готова.
Осталось сделать инициализацию и прослушку свойств FirstImage и SecondImage.

Добавлено через 1 минуту
Посмотрите тему "INPC и получение данных из Модели" в цикле Готовые решения, примеры и рекомендации начинающим на WPF [Элд Хасп]
1
 Аватар для ShmelVG
171 / 106 / 51
Регистрация: 27.11.2015
Сообщений: 1,269
02.05.2019, 22:44  [ТС]
Элд Хасп, а где вообще правильнее делать в моей ситуации поворот и смещение, во view или vm?
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16164 / 11284 / 2891
Регистрация: 21.04.2018
Сообщений: 33,169
Записей в блоге: 2
02.05.2019, 22:48
Цитата Сообщение от ShmelVG Посмотреть сообщение
.ээмм, у меня сейчас нет текстбоксов))
И не надо. Это я просто писал о примере реализации.
С ними возможно сделать чисто в XAML, но будет очень неудобно пользоваться. Так как не будет кнопок.

Добавлено через 2 минуты
Цитата Сообщение от ShmelVG Посмотреть сообщение
вообще правильнее делать в моей ситуации поворот и смещение, во view или vm?
По любому Вам нужно грузить картинки, для этого надо обращаться к данным, то есть VM по любому будет.
Да, её можно спрятать в CB окна, но она будет - пусть и не явно.
Но с такой реализацией будет труднее работать.
0
 Аватар для ShmelVG
171 / 106 / 51
Регистрация: 27.11.2015
Сообщений: 1,269
03.05.2019, 16:43  [ТС]
Элд Хасп, clr кидает мне много ошибок, типа той что была ранее (№40), я пытаюсь подключить команду на открытие фото, но нет реации, хотя при отладке, при запуске он заходит в команду, но при нажатии кнопки , не выполняется, опять что-то с пространством Имен((

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
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
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
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
<Window x:Class="PhotoGluer.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:PhotoGluer.ViewModels"
        mc:Ignorable="d"
        Title="PhotoGluer" Height="800" Width="1200">
 
    <Window.Resources>
        <local:MainVM x:Key="viewModel">
            <local:MainVM.Width>700</local:MainVM.Width>
            <local:MainVM.Height>1000</local:MainVM.Height>
        </local:MainVM>
    </Window.Resources>
    
    <Window.DataContext>
        <Binding Mode="OneWay" Source="{StaticResource viewModel}"/>
    </Window.DataContext>
    
    <Grid>
 
        <Border 
            BorderBrush="Gray"
            BorderThickness="7">
 
            <Grid>
 
                <Grid.ColumnDefinitions>
                    <ColumnDefinition></ColumnDefinition>
                    <ColumnDefinition Width="0.3*"></ColumnDefinition>
                </Grid.ColumnDefinitions>
 
                <Grid Grid.Column="0">
 
                    <Border 
                        Grid.Row="0"
                        BorderBrush="Black"
                        BorderThickness="3"
                        Grid.Column="0"
                        Margin="5">
 
                        <ScrollViewer
                            HorizontalScrollBarVisibility="Auto"
                            VerticalScrollBarVisibility="Auto">
 
                            <StackPanel>
                                <Canvas 
                                    Grid.Column="0">
 
                                    <Image x:Name="ImageCam1" 
                                           Source="{Binding FirstImage}"  
                                           Stretch="None">
 
                                        <Image.LayoutTransform>
                                            <TransformGroup>
                                                <ScaleTransform/>
                                                <SkewTransform/>
                                                <RotateTransform Angle="{Binding Angle}"/>
                                                <TranslateTransform/>
                                            </TransformGroup>
                                        </Image.LayoutTransform>
                                    </Image>
 
                                    <Image x:Name="ImageCam2" 
                                           Source="{Binding SecondImage}" 
                                           RenderTransformOrigin="0.5,0.5" 
                                           Stretch="None">
 
                                        <Image.LayoutTransform>
                                            <TransformGroup>
                                                <ScaleTransform/>
                                                <SkewTransform/>
                                                <RotateTransform Angle="{Binding Angle}"/>
                                                <TranslateTransform/>
                                            </TransformGroup>
                                        </Image.LayoutTransform>
                                    </Image>
 
                                </Canvas>
 
                            </StackPanel>
 
                        </ScrollViewer>
 
                    </Border>
 
                </Grid>
 
                <Grid Grid.Column="1">
 
                    <Grid.RowDefinitions>
                        <RowDefinition></RowDefinition>
                        <RowDefinition></RowDefinition>
                        <RowDefinition></RowDefinition>
                    </Grid.RowDefinitions>
 
                    <Grid Grid.Row="0">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition></ColumnDefinition>
                            <ColumnDefinition></ColumnDefinition>
                        </Grid.ColumnDefinitions>
 
                        <Grid.RowDefinitions>
                            <RowDefinition Height="0.5*"></RowDefinition>
                            <RowDefinition Height="0.5*"></RowDefinition>
                            <RowDefinition></RowDefinition>
                            <RowDefinition></RowDefinition>
                            <RowDefinition></RowDefinition>
                        </Grid.RowDefinitions>
 
                        
                        <TextBlock  
                                    Grid.ColumnSpan="2"
                                    Grid.Row="1" 
                                    HorizontalAlignment="Center" 
                                    VerticalAlignment="Center" 
                                    Text="Смещение X,Y" 
                                    FontSize="18"/>
 
                        <Button  
                                    Grid.Column="0"
                                    Grid.Row="2" 
                                    HorizontalAlignment="Center" 
                                    VerticalAlignment="Center" 
                                    Content="Фото 1"
                                    Padding="10 5"
                                    FontSize="18"
                                    Command="{ Binding LoadCommand }"/>
 
                        <Button 
                                    Grid.Column="0" 
                                    Grid.Row="3" 
                                    HorizontalAlignment="Center" 
                                    VerticalAlignment="Center" 
                                    Content="Фото 2"
                                    Padding="10 5"
                                    FontSize="18"
                                    Command="{ Binding LoadCommand }"/>
 
                        <TextBlock 
                                    Grid.Column="1" 
                                    Grid.Row="2" 
                                    Height="40" 
                                    FontSize="24" 
                                    VerticalAlignment="Center"                     
                                    HorizontalAlignment="Center"
                                    Width="130"/>
 
                        <TextBlock 
                                    Grid.Column="1" 
                                    Grid.Row="3" 
                                    Height="40" 
                                    FontSize="24" 
                                    VerticalAlignment="Center"                     
                                    HorizontalAlignment="Left"
                                    Width="130"/>
 
                        <TextBlock 
                                    Grid.Column="0" 
                                    Grid.Row="4" 
                                    HorizontalAlignment="Center" 
                                    VerticalAlignment="Center" 
                                    Text="Смещение:" 
                                    FontSize="18"/>
 
                        <TextBlock 
                                    Grid.Column="1" 
                                    Grid.Row="4" 
                                    Height="40" 
                                    FontSize="24" 
                                    VerticalAlignment="Center"
                                    HorizontalAlignment="Left"
                                    Width="130" />
                    </Grid>
                    <Grid Grid.Row="1">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition></ColumnDefinition>
                            <ColumnDefinition></ColumnDefinition>
                        </Grid.ColumnDefinitions>
 
                        <Grid.RowDefinitions>
                            <RowDefinition></RowDefinition>
                            <RowDefinition></RowDefinition>
                            <RowDefinition></RowDefinition>
                            <RowDefinition></RowDefinition>
                            <RowDefinition></RowDefinition>
                            <RowDefinition></RowDefinition>
                        </Grid.RowDefinitions>
 
                        <TextBlock 
                                Grid.ColumnSpan="2" 
                                Grid.Row="0" 
                                TextWrapping="Wrap" 
                                Text="Повернуть" 
                                VerticalAlignment="Center" 
                                HorizontalAlignment="Center"
                                FontSize="18"/>
 
                        <Button 
                                Grid.Column="0"
                                Grid.Row="1" 
                                HorizontalAlignment="Center"
                                VerticalAlignment="Center" 
                                Content="left 1"
                                FontSize="18"/>
 
                        <Button 
                                Grid.Column="0"
                                Grid.Row="2" 
                                HorizontalAlignment="Center"
                                VerticalAlignment="Center" 
                                Content="left 10"
                                FontSize="18"/>
                        <Button 
                                Grid.Column="0"
                                Grid.Row="3" 
                                HorizontalAlignment="Center"
                                VerticalAlignment="Center" 
                                Content="left 45"
                                FontSize="18"/>
 
                        <Button 
                                Grid.Column="0"
                                Grid.Row="4" 
                                HorizontalAlignment="Center"
                                VerticalAlignment="Center" 
                                Content="left 90"
                                FontSize="18"/>
 
                        <Button 
                                Grid.Column="1"
                                Grid.Row="1" 
                                HorizontalAlignment="Center"
                                VerticalAlignment="Center" 
                                Content="right 1"
                                FontSize="18"/>
 
                        <Button 
                                Grid.Column="1"
                                Grid.Row="2" 
                                HorizontalAlignment="Center"
                                VerticalAlignment="Center" 
                                Content="right 10"
                                FontSize="18"/>
 
                        <Button 
                                Grid.Column="1"
                                Grid.Row="3" 
                                HorizontalAlignment="Center"
                                VerticalAlignment="Center" 
                                Content="right 45"
                                FontSize="18"/>
 
                        <Button 
                                Grid.Column="1"
                                Grid.Row="4" 
                                HorizontalAlignment="Center"
                                VerticalAlignment="Center" 
                                Content="right 90"
                                FontSize="18"/>
 
                    </Grid>
 
                    <Grid Grid.Row="2">
 
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition></ColumnDefinition>
                            <ColumnDefinition></ColumnDefinition>
                            <ColumnDefinition></ColumnDefinition>
                        </Grid.ColumnDefinitions>
 
                        <Grid.RowDefinitions>
                            <RowDefinition></RowDefinition>
                            <RowDefinition></RowDefinition>
                            <RowDefinition></RowDefinition>
                        </Grid.RowDefinitions>
 
                        <Button 
                                    Grid.Column="1" 
                                    Grid.Row="0" 
                                    Content="Вверх" 
                                    FontWeight="Bold" 
                                    FontSize="16" 
                                    Margin="2"
                                    BorderThickness="2"
                                    Command="{Binding MoveCommand}"
                                    CommandParameter="Up"/>
 
                        <Button 
                                    Grid.Column="0" 
                                    Grid.Row="1" 
                                    Content="Влево" 
                                    FontWeight="Bold" 
                                    FontSize="16" 
                                    Margin="2"
                                    BorderThickness="2"
                                    Command="{Binding MoveCommand}"
                                    CommandParameter="Left"/>
 
                        <Button 
                                    Grid.Column="2" 
                                    Grid.Row="1" 
                                    Content="Вправо" 
                                    FontWeight="Bold" 
                                    Margin="2"
                                    FontSize="16" 
                                    BorderThickness="2"
                                    Command="{Binding MoveCommand}"
                                    CommandParameter="Rigth"/>
 
                        <Button 
                                    Grid.Column="1" 
                                    Grid.Row="2" 
                                    Content="Вниз" 
                                    FontWeight="Bold" 
                                    Margin="2"
                                    FontSize="16" 
                                    BorderThickness="2"
                                    Command="{Binding MoveCommand}"
                                    CommandParameter="Down"/>
 
                    </Grid>
 
                </Grid>
 
            </Grid>
 
        </Border>
 
    </Grid>
 
</Window>
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16164 / 11284 / 2891
Регистрация: 21.04.2018
Сообщений: 33,169
Записей в блоге: 2
03.05.2019, 17:30
Цитата Сообщение от ShmelVG Посмотреть сообщение
clr кидает мне много ошибок,
Скиньте проект сюда - посмотрю.
Постараюсь ответить сегодня.
0
 Аватар для ShmelVG
171 / 106 / 51
Регистрация: 27.11.2015
Сообщений: 1,269
03.05.2019, 17:43  [ТС]
Элд Хасп, PhotoGluer.rar
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16164 / 11284 / 2891
Регистрация: 21.04.2018
Сообщений: 33,169
Записей в блоге: 2
03.05.2019, 19:50
ShmelVG, Вы торопитесь с созданием View.
Опыта, что бы пропускать какие-то шаги последовательности создания у Вас пока нет.

Поэтому придерживайтесь, пока не наберётесь опыты, следующей последовательности:
  • Модель, включая все типы для управления данными. В этом случае это класс ImageModify
  • Интерфейс VM - его пока не создавали. Назовём его IPhotoGluer.
  • ViewModel Data Designed - Модель-Представления времени разработки. Она должна реализовывать интерфейс IPhotoGluer и реализовывать полностью или почти полностью сторону VM обращённую к View. Назовём его PhotoGluerVMDD.
  • View
  • ViewModel - чаще всего как производный от VMDD. Назовём его PhotoGluerVM. Прописывается сторона отвечающая за связь с Model.

В самой View надо создать
  • Подключение к типу IPhotoGluer
  • Словарь с экземпляром PhotoGluerVMDD
  • Шаблоны для типовых данных. В нашем случае один шаблон для типа ImageModify

После создания и отладки View будет создаваться PhotoGluerVM.

Добавлено через 1 минуту
P.S. Пока занят. Попозже посмотрю Ваш проект и напишу по нему замечания.
0
 Аватар для ShmelVG
171 / 106 / 51
Регистрация: 27.11.2015
Сообщений: 1,269
03.05.2019, 20:07  [ТС]
Элд Хасп,
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Интерфейс VM - его пока не создавали. Назовём его IPhotoGluer.
, а это разве не MainVM?
Я если честно совсем запутался, у меня там есть этот класс, который связывает по идее модель и вью, но я не очень понял зачем создавать в vm ещё несколько классов
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16164 / 11284 / 2891
Регистрация: 21.04.2018
Сообщений: 33,169
Записей в блоге: 2
03.05.2019, 23:18
Цитата Сообщение от ShmelVG Посмотреть сообщение
, а это разве не MainVM?
Это ViewModel.
Её создают в последнюю очередь.
Я поэтому и пишу Вам, что поторопились.

Цитата Сообщение от ShmelVG Посмотреть сообщение
Я если честно совсем запутался...
Я пока занят, но вроде через часок освобожусь и займусь Ваши проектом.
Распишу пошагово что и как делать надо.
Что бы Вам понятно была.
Посмотрите, что будет непонятно - поинтересуетесь.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16164 / 11284 / 2891
Регистрация: 21.04.2018
Сообщений: 33,169
Записей в блоге: 2
03.05.2019, 23:24
Цитата Сообщение от ShmelVG Посмотреть сообщение
PhotoGluer.rar
Классы не имеющее непосредственное отношение к MVVM проекту желательно вынести в отдельную библиотеку. Что бы при изменении проекта их каждый раз не пересобирать. Так же иногда дизайнер-редактор Студии (а XAML всегда) разбирает типы не по исходному коду, а по сборке. Лучше пусть сборка будет всегда в нормальном неизменном виде.

Класс ImageModify, вреде, нормально сделан.

Теперь по канонам создания MVVM надо создавать View. ViewModel - это согласующее звено между View и Model. А так как View ещё нет, то согласовывать с чем неизвестно. Но возникает другая проблема. Свойства View надо к чему-то привязывать, но ViewModel ещё нет - замкнутый круг. Для выхода из этого круга создаётся интерфейс ViewModel. Это как некий стандарт для подключения View. Передав потом этот интерфейс разработчикам ViewModel можно быть уверенным, что View с ним будет нормально работать.

В нашем случае интерфейс должен содержать все свойства VM обращённые к View и наследовать интерфейс INPC.

Вот этот интерфейс. Находится он в пространстве PhotoGluer.ViewModels так как VM тоже должна иметь доступ к нему
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
namespace PhotoGluer.ViewModels
{
    public interface IPhotoGluer : INotifyPropertyChanged
    {
        #region Свойства
        /// <summary>Хранение первой картинки и действия</summary>
        ImageModify FirstImage { get; set; }
        /// <summary>Хранение второй картинки и действия</summary>
        ImageModify SecondImage { get; set; }
        /// <summary>Ширина холста</summary>
        double Width { get; set; }
        /// <summary>Высота холста</summary>
        double Height { get; set; }
        /// <summary>Смещение по горизонтали между картинками</summary>
        double OffsetLeft { get; set; }
        /// <summary>Смещение по вертикали между картинками</summary>
        double OffsetTop { get; set; }
        /// <summary>Смещение поворота между картинками</summary>
        double OffsetAngle { get; set; }
        /// <summary>Для привязки ToggleButton</summary>
        bool? IsSecondSelected { get; set; }
        /// <summary>Ссылка на выделенную картинку</summary>
        ImageModify SelectedImage { get; set; }
 
        #endregion
 
        #region Команды
 
        /// <summary>Команда загрузки картинки</summary>
        RelayCommand LoadCommand { get; }
        /// <summary>Команда смещения картинки</summary>
        RelayCommand MoveCommand { get; }
        /// <summary>Команда поворота картинки</summary>
        RelayCommand RotateCommand { get; }
 
        #endregion
 
    }
}
Добавлено через 5 минут
Цитата Сообщение от ShmelVG Посмотреть сообщение
я пытаюсь подключить команду на открытие фото,
Теперь мы можем в View объявить тип привязываемой VM
XML
1
2
3
4
5
6
7
8
9
10
<Window x:Class="PhotoGluer.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        Title="PhotoGluer" Height="800" Width="1200"
        xmlns:viewModels="clr-namespace:PhotoGluer.ViewModels"
        d:DataContext="{x:Type viewModels:IPhotoGluer}"
        >
1
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16164 / 11284 / 2891
Регистрация: 21.04.2018
Сообщений: 33,169
Записей в блоге: 2
03.05.2019, 23:51
Чтобы не загромождать View создадим словарь ресурсов куда вынесем все стили и шаблоны.
Пока впишем туда только один шаблон данных для ImageModify

Словарь PhotoGluerDict
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:model="clr-namespace:PhotoGluer.Models"
                    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
                    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                    mc:Ignorable="d"
                    >
    <DataTemplate DataType="{x:Type model:ImageModify}" x:Key="DataTemplate.ImageModify">
        <Border BorderBrush="LightSkyBlue">
            <Border.Style>
                <Style TargetType="Border">
                    <Setter Property="BorderThickness" Value="0"/>
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding IsSelected}" Value="true">
                            <Setter Property="BorderThickness" Value="2"/>
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </Border.Style>
            <Image Source="{Binding Image}" 
                   RenderTransformOrigin="0.5,0.5">
                <Image.RenderTransform>
                    <TransformGroup>
                        <ScaleTransform/>
                        <SkewTransform/>
                        <RotateTransform Angle="{Binding Angle}"/>
                        <TranslateTransform/>
                    </TransformGroup>
                </Image.RenderTransform>
            </Image>
        </Border>
    </DataTemplate>
</ResourceDictionary>
И подключим этот словарь к окну
XML
12
13
14
15
16
17
18
    <Window.Resources>
        <!--<viewModels:MainVM x:Key="viewModel">
            <viewModels:MainVM.Width>700</viewModels:MainVM.Width>
            <viewModels:MainVM.Height>1000</viewModels:MainVM.Height>
        </viewModels:MainVM>-->
        <ResourceDictionary Source="PhotoGluerDict.xaml"/>
    </Window.Resources>
1
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16164 / 11284 / 2891
Регистрация: 21.04.2018
Сообщений: 33,169
Записей в блоге: 2
04.05.2019, 00:09
Цитата Сообщение от ShmelVG Посмотреть сообщение
, PhotoGluer.rar
В ресурсах Canvas определим дефолтный стиль для ContentPresenter.
И, кстати, я не понял, а зачем Вы Canvas заключили в StackPanel?

Canvas в XAML
XML
1
2
3
4
5
6
7
8
9
10
11
12
                                <Canvas >
                                    <Canvas.Resources>
                                        <Style TargetType="ContentPresenter">
                                            <Setter Property="Content" Value="{Binding}"/>
                                            <Setter Property="ContentTemplate" Value="{StaticResource DataTemplate.ImageModify}"/>
                                            <Setter Property="Canvas.Left" Value="{Binding Left}"/>
                                            <Setter Property="Canvas.Top" Value="{Binding Top}"/>
                                        </Style>
                                    </Canvas.Resources>
                                    <ContentPresenter DataContext="{Binding FirstImage}"/>
                                    <ContentPresenter DataContext="{Binding SecondImage}"/>
                                </Canvas>
1
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16164 / 11284 / 2891
Регистрация: 21.04.2018
Сообщений: 33,169
Записей в блоге: 2
04.05.2019, 00:31
Цитата Сообщение от ShmelVG Посмотреть сообщение
PhotoGluer.rar
Теперь кнопки.

Кнопки загрузки в параметрах должны получить какое изображение они будут загружать
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
                        <Button Grid.Column="0" 
                                Grid.Row="2" 
                                HorizontalAlignment="Center" 
                                VerticalAlignment="Center" 
                                Content="Фото 1"
                                Padding="10 5"
                                FontSize="18"
                                Command="{Binding LoadCommand}"
                                CommandParameter="{Binding FirstImage}"/>
 
                        <Button Grid.Column="0" 
                                Grid.Row="3" 
                                HorizontalAlignment="Center" 
                                VerticalAlignment="Center" 
                                Content="Фото 2"
                                Padding="10 5"
                                FontSize="18"
                                Command="{Binding LoadCommand}"
                                CommandParameter="{Binding SecondImage}"/>

Кнопки поворота должны получать в параметрах угол поворота
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
                        <Button Grid.Column="0"
                                Grid.Row="1" 
                                HorizontalAlignment="Center"
                                VerticalAlignment="Center" 
                                Content="left 1"
                                FontSize="18"
                                Command="{Binding RotateCommand}"
                                CommandParameter="-1"/>
 
                        <Button Grid.Column="0"
                                Grid.Row="2" 
                                HorizontalAlignment="Center"
                                VerticalAlignment="Center" 
                                Content="left 10"
                                FontSize="18"
                                Command="{Binding RotateCommand}"
                                CommandParameter="-10"/>
И все однотипные настройки элементов выносите в стили. Намного удобнее.

Осталось подключить ToggleButton. Стиль из поста с ToggleButton определим в словаре
И сама кнопка с поясняющим текстом
XML
309
310
311
312
313
314
315
316
317
318
319
320
321
                    <StackPanel Grid.Row="3">
                        <TextBlock Text="Выбор изображения" HorizontalAlignment="Center"/>
                        <ToggleButton 
                                  IsChecked="{Binding IsSecondSelected}"
                                  Style="{StaticResource ToggleButton.Style}"
                                  Margin="10" 
                                  VerticalAlignment="Center">
                            <ToggleButton.Resources>
                                <sys:String  x:Key="ToggleButton.Text.Check">Второе</sys:String>
                                <sys:String  x:Key="ToggleButton.Text.UnCheck">Первое</sys:String>
                            </ToggleButton.Resources>
                        </ToggleButton>
                    </StackPanel>
На сегодня - всё.
Что непонятно пишите.
1
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16164 / 11284 / 2891
Регистрация: 21.04.2018
Сообщений: 33,169
Записей в блоге: 2
04.05.2019, 13:35
Цитата Сообщение от ShmelVG Посмотреть сообщение
PhotoGluer.rar
Теперь дополним View стилями.
Вообще-то, они должны создаваться до View и потом использоваться в View.
Но у Вас View уже создана. Так, что я возьму за образец вид элементов в View и перенесу их в стили.

Все стили будут в словаре.

Сначала уже созданный стиль ContentPresenter для Canvas
XML
1
2
3
4
5
6
    <Style TargetType="ContentPresenter" x:Key="Style.ContentPresenter.Canvas">
        <Setter Property="Content" Value="{Binding}"/>
        <Setter Property="ContentTemplate" Value="{StaticResource DataTemplate.ImageModify}"/>
        <Setter Property="Canvas.Left" Value="{Binding Left}"/>
        <Setter Property="Canvas.Top" Value="{Binding Top}"/>
    </Style>
С ним Canvas будет выглядеть так
XML
52
53
54
55
56
57
58
                                <Canvas>
                                    <Canvas.Resources>
                                        <Style TargetType="ContentPresenter" BasedOn="{StaticResource Style.ContentPresenter.Canvas}"/>
                                    </Canvas.Resources>
                                    <ContentPresenter DataContext="{Binding FirstImage}"/>
                                    <ContentPresenter DataContext="{Binding SecondImage}"/>
                                </Canvas>
Следующий стиль для кнопок загрузки изображений
XML
1
2
3
4
5
6
7
    <Style TargetType="Button" x:Key="Style.Button.LoadImage">
        <Setter Property="HorizontalAlignment" Value="Center"/>
        <Setter Property="VerticalAlignment" Value="Center"/>
        <Setter Property="Padding" Value="10, 5"/>
        <Setter Property="FontSize" Value="18"/>
        <Setter Property="Command" Value="{Binding LoadCommand}"/>
    </Style>
Код кнопок получится такой
XML
1
2
3
4
5
6
7
8
9
                        <Button Grid.Row="2" 
                                Content="Фото 1"
                                CommandParameter="{Binding FirstImage}"
                                Style="{StaticResource Style.Button.LoadImage}"/>
 
                        <Button Grid.Row="3" 
                                Content="Фото 2"
                                CommandParameter="{Binding SecondImage}"
                                Style="{StaticResource Style.Button.LoadImage}"/>
1
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16164 / 11284 / 2891
Регистрация: 21.04.2018
Сообщений: 33,169
Записей в блоге: 2
04.05.2019, 14:19
Цитата Сообщение от ShmelVG Посмотреть сообщение
PhotoGluer.rar
Следующий стиль - стиль для TextBlock смещения.
Чтобы была рамочка вокруг надо дополнить их Border
XML
1
2
3
4
5
6
    <Style TargetType="TextBlock" x:Key="Style.TextBlock.Offset">
        <Setter Property="FontSize" Value="24"/>
        <Setter Property="VerticalAlignment" Value="Center"/>
        <Setter Property="HorizontalAlignment" Value="Stretch"/>
        <Setter Property="TextAlignment" Value="Center"/>
    </Style>
TxtBlock которые выводят смещение для красоты лучше дополнить рамочкой. Так же надо в TextBlock для координат (X, Y) указать привязку к нескольким значениям (Left, Top). Это делается через вставку Run

Общий Grid теперь выглядит так
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition/>
                            <ColumnDefinition/>
                        </Grid.ColumnDefinitions>
 
                        <Grid.RowDefinitions>
                            <RowDefinition Height="0.5*"/>
                            <RowDefinition Height="0.5*"/>
                            <RowDefinition/>
                            <RowDefinition/>
                            <RowDefinition/>
                        </Grid.RowDefinitions>
                        <TextBlock  Grid.ColumnSpan="2"
                                    Grid.Row="1" 
                                    Text="Смещение X,Y" 
                                    FontSize="18"
                                    Style="{StaticResource Style.TextBlock.Offset}"/>
 
                        <Button Grid.Row="2" 
                                Content="Фото 1"
                                CommandParameter="{Binding FirstImage}"
                                Style="{StaticResource Style.Button.LoadImage}"/>
 
                        <Button Grid.Row="3" 
                                Content="Фото 2"
                                CommandParameter="{Binding SecondImage}"
                                Style="{StaticResource Style.Button.LoadImage}"/>
 
                        <Border Margin="5" 
                                BorderBrush="LightGray" BorderThickness="1" 
                                Grid.Column="1" Grid.Row="2">
                            <TextBlock Style="{StaticResource Style.TextBlock.Offset}">
                                <Run Text="{Binding FirstImage.Left}"/>
                                <Run Text=", "/>
                                <Run Text="{Binding FirstImage.Top}"/>
                            </TextBlock>
                        </Border>
 
                        <Border Margin="5" 
                                BorderBrush="LightGray" BorderThickness="1" 
                                Grid.Column="1" Grid.Row="3">
                            <TextBlock Style="{StaticResource Style.TextBlock.Offset}">
                                <Run Text="{Binding SecondImage.Left}"/>
                                <Run Text=", "/>
                                <Run Text="{Binding SecondImage.Top}"/>
                            </TextBlock>
                        </Border>
 
                        <TextBlock Style="{StaticResource Style.TextBlock.Offset}"
                                   Grid.Row="4" 
                                   Text="Относительное:" 
                                    FontSize="18"/>
 
                        <Border Margin="5" 
                                BorderBrush="LightGray" BorderThickness="1" 
                                Grid.Column="1" Grid.Row="4">
                            <TextBlock Style="{StaticResource Style.TextBlock.Offset}">
                                <Run Text="{Binding OffsetLeft}"/>
                                <Run Text=", "/>
                                <Run Text="{Binding OffsetTop}"/>
                            </TextBlock>
                        </Border>
                    </Grid>
1
 Аватар для ShmelVG
171 / 106 / 51
Регистрация: 27.11.2015
Сообщений: 1,269
04.05.2019, 15:26  [ТС]
Элд Хасп,
Цитата Сообщение от Элд Хасп Посмотреть сообщение
зачем Вы Canvas заключили в StackPanel?
- виноват, забыл убрать следы экспериментов)
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Осталось подключить ToggleButton.
- всё шло хорошо до этого момента,
Цитата Сообщение от Элд Хасп Посмотреть сообщение
И сама кнопка с поясняющим текстом
- этот код должен быть + к открыть "Фото 1" и "Фото 2"?

Вот с ToggleButton я не разобрался, в этом месте, что нужно добавить в словарь, а что во view? Нужно ли создавать новый словарь и подключать его ко view?

На данный момент ни одна из кнопок не работает по нажатии (дальше к стилям ещё не спускался, запнулся на этом месте)
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16164 / 11284 / 2891
Регистрация: 21.04.2018
Сообщений: 33,169
Записей в блоге: 2
04.05.2019, 15:50
Цитата Сообщение от ShmelVG Посмотреть сообщение
PhotoGluer.rar
Не нравится мне что-то....
По-моему надо Left, Top и Angle вынести в отдельный класс.
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
using CommLibrary;
namespace PhotoGluer.Models
{
    public class ImagePositioning : OnPropertyChangedClass
    {
        #region Поля для хранения значений свойств
        private double _top;
        private double _left;
        private double _angle;
        #endregion
 
        #region Свойства
        /// <summary>Смешение сверху позиции картинки</summary>
        public double Top { get => _top; set { _top = value; OnPropertyChanged(); } }
        /// <summary>Смешение слева позиции картинки</summary>
        public double Left { get => _left; set { _left = value; OnPropertyChanged(); } }
        /// <summary>Поворот картинки</summary>
        public double Angle { get => _angle; set { _angle = value; OnPropertyChanged(); } }
        #endregion
    }
}
И внести изменение в класс ImageModify и интерфейс IPhotoGluer
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
using CommLibrary;
using System;
using System.Windows.Media;
 
namespace PhotoGluer.Models
{
    public class ImageModify : OnPropertyChangedClass
    {
        #region Поля для хранения значений свойств
        private ImageSource _image;
        private object _source;
        private double _width;
        private double _height;
        private bool _isSelected;
        #endregion
 
        #region Свойства
        /// <summary>Источник картинки</summary>
        public ImageSource Image { get => _image; set { _image = value; OnPropertyChanged(); } }
        /// <summary>Сохранение ссылки на источник картинки</summary>
        public object Source { get => _source; set { _source = value; OnPropertyChanged(); } }
        /// <summary>Ширина картинки</summary>
        public double Width { get => _width; set { _width = value; OnPropertyChanged(); } }
        /// <summary>Высота картинки</summary>
        public double Height { get => _height; set { _height = value; OnPropertyChanged(); } }
        /// <summary>Идентификация выбранной картинки</summary>
        public bool IsSelected { get => _isSelected; set { _isSelected = value; OnPropertyChanged(); } }
        /// <summary>Позиционирование картинки</summary>
        public ImagePositioning Position { get; set; }
        #endregion
 
        private static readonly ImageSourceConverter imageSourceConverter = new ImageSourceConverter();
 
        internal void LoadImage(object imageSource)
        {
            try
            {
                Image = (ImageSource)imageSourceConverter.ConvertFrom(imageSource);
                Source = imageSource;
                Width = Image.Width; // Вот это надо проверять
                Height = Image.Height; // не знаю это реальные размеры или приведённые
                Position.Top = Position.Left = Position.Angle = 0;
            }
            catch (Exception)
            {
                throw new Exception("Ошибка загрузки изображения");
            }
        }
    }
}
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
using CommLibrary;
using PhotoGluer.Models;
using System.ComponentModel;
 
namespace PhotoGluer.ViewModels
{
    public interface IPhotoGluer : INotifyPropertyChanged
    {
        #region Свойства
        /// <summary>Хранение первой картинки и действия</summary>
        ImageModify FirstImage { get; }
        /// <summary>Хранение второй картинки и действия</summary>
        ImageModify SecondImage { get; }
        /// <summary>Ширина холста</summary>
        double Width { get; }
        /// <summary>Высота холста</summary>
        double Height { get; }
        /// <summary>Смещение между картинками</summary>
        ImagePositioning Offset { get; }
        /// <summary>Для привязки ToggleButton</summary>
        bool? IsSecondSelected { get; set; }
        /// <summary>Ссылка на выделенную картинку</summary>
        ImageModify SelectedImage { get; set; }
 
        #endregion
 
        #region Команды
 
        /// <summary>Команда загрузки картинки</summary>
        RelayCommand LoadCommand { get; }
        /// <summary>Команда смещения картинки</summary>
        RelayCommand MoveCommand { get; }
        /// <summary>Команда поворота картинки</summary>
        RelayCommand RotateCommand { get; }
 
        #endregion
    }
}
В словарь ресурсов добавляем стиль Label для вывода смещений
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
    <Style TargetType="Label" x:Key="Style.Label.Offset">
        <Setter Property="Margin" Value="5"/>
        <Setter Property="BorderBrush" Value="LightGray"/>
        <Setter Property="BorderThickness" Value="1"/>
        <Setter Property="Content">
            <Setter.Value>
                <TextBlock Style="{DynamicResource Style.TextBlock.Offset}" 
                           DataContext="{x:Type model:ImagePositioning}">
                    <Run Text="{Binding Left}"/>
                    <Run Text=", "/>
                    <Run Text="{Binding Top}"/>
                    <Run Text=", "/>
                    <Run Text="{Binding Angle}"/>
                     <Run Text="°"/>
               </TextBlock>
            </Setter.Value>
        </Setter>
    </Style>
И изменяем под него Grid
XML
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
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition/>
                            <ColumnDefinition/>
                        </Grid.ColumnDefinitions>
 
                        <Grid.RowDefinitions>
                            <RowDefinition Height="0.5*"/>
                            <RowDefinition Height="0.5*"/>
                            <RowDefinition/>
                            <RowDefinition/>
                            <RowDefinition/>
                        </Grid.RowDefinitions>
                        <TextBlock  Grid.ColumnSpan="2"
                                    Grid.Row="1" 
                                    Text="Смещение X,Y" 
                                    FontSize="18"
                                    Style="{StaticResource Style.TextBlock.Offset}"/>
 
                        <Button Grid.Row="2" 
                                Content="Фото 1"
                                CommandParameter="{Binding FirstImage}"
                                Style="{StaticResource Style.Button.LoadImage}"/>
                        <Button Grid.Row="3" 
                                Content="Фото 2"
                                CommandParameter="{Binding SecondImage}"
                                Style="{StaticResource Style.Button.LoadImage}"/>
                        
                        <Label Style="{StaticResource Style.Label.Offset}" 
                               DataContext="{Binding FirstImage.Position, Mode=OneWay}"
                               Grid.Column="1" Grid.Row="2"/>
                        <Label Style="{StaticResource Style.Label.Offset}" 
                               DataContext="{Binding SecondImage.Position, Mode=OneWay}"
                               Grid.Column="1" Grid.Row="3"/>
                        <Label Style="{StaticResource Style.Label.Offset}" 
                               DataContext="{Binding Offset, Mode=OneWay}"
                               Grid.Column="1" Grid.Row="4"/>
 
                        <TextBlock Style="{StaticResource Style.TextBlock.Offset}"
                                   Grid.Row="4" 
                                   Text="Относительное:" 
                                   FontSize="18"/>
                    </Grid>
1
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16164 / 11284 / 2891
Регистрация: 21.04.2018
Сообщений: 33,169
Записей в блоге: 2
04.05.2019, 15:52
Цитата Сообщение от ShmelVG Посмотреть сообщение
Вот с ToggleButton я не разобрался, в этом месте, что нужно добавить в словарь, а что во view? Нужно ли создавать новый словарь и подключать его ко view?
Все стили добавляем в словарь, чтобы не загромождать код окна. В окне только сами элементы

Словарь на данный момент
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
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
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:model="clr-namespace:PhotoGluer.Models"
                    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
                    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                    xmlns:sys="clr-namespace:System;assembly=mscorlib"
                    mc:Ignorable="d"
                    >
    <DataTemplate DataType="{x:Type model:ImageModify}" x:Key="DataTemplate.ImageModify">
        <Border BorderBrush="LightSkyBlue">
            <Border.Style>
                <Style TargetType="Border">
                    <Setter Property="BorderThickness" Value="0"/>
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding IsSelected}" Value="true">
                            <Setter Property="BorderThickness" Value="2"/>
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </Border.Style>
            <Image Source="{Binding Image}" 
                   RenderTransformOrigin="0.5,0.5">
                <Image.RenderTransform>
                    <TransformGroup>
                        <ScaleTransform/>
                        <SkewTransform/>
                        <RotateTransform Angle="{Binding Angle}"/>
                        <TranslateTransform/>
                    </TransformGroup>
                </Image.RenderTransform>
            </Image>
        </Border>
    </DataTemplate>
    <Style TargetType="Label" x:Key="Style.Label.Offset">
        <Setter Property="Margin" Value="5"/>
        <Setter Property="BorderBrush" Value="LightGray"/>
        <Setter Property="BorderThickness" Value="1"/>
        <Setter Property="Content">
            <Setter.Value>
                <TextBlock Style="{DynamicResource Style.TextBlock.Offset}" 
                           DataContext="{x:Type model:ImagePositioning}">
                    <Run Text="{Binding Left}"/>
                    <Run Text=", "/>
                    <Run Text="{Binding Top}"/>
                    <Run Text=", "/>
                    <Run Text="{Binding Angle}"/>
                     <Run Text="°"/>
               </TextBlock>
            </Setter.Value>
        </Setter>
    </Style>
    <Style TargetType="TextBlock" x:Key="Style.TextBlock.Offset">
        <Setter Property="FontSize" Value="24"/>
        <Setter Property="VerticalAlignment" Value="Center"/>
        <Setter Property="HorizontalAlignment" Value="Stretch"/>
        <Setter Property="TextAlignment" Value="Center"/>
    </Style>
    <Style TargetType="Button" x:Key="Style.Button.LoadImage">
        <Setter Property="HorizontalAlignment" Value="Center"/>
        <Setter Property="VerticalAlignment" Value="Center"/>
        <Setter Property="Padding" Value="10, 5"/>
        <Setter Property="FontSize" Value="18"/>
        <Setter Property="Command" Value="{Binding LoadCommand}"/>
    </Style>
    <Style TargetType="ContentPresenter" x:Key="Style.ContentPresenter.Canvas">
        <Setter Property="Content" Value="{Binding}"/>
        <Setter Property="ContentTemplate" Value="{StaticResource DataTemplate.ImageModify}"/>
        <Setter Property="Canvas.Left" Value="{Binding Left}"/>
        <Setter Property="Canvas.Top" Value="{Binding Top}"/>
    </Style>
    <SolidColorBrush x:Key="ToggleButton.Color.Check" Color="LightSkyBlue" />
    <SolidColorBrush x:Key="ToggleButton.Color.UnCheck" Color="White"/>
    <sys:String  x:Key="ToggleButton.Text.Check">Buy</sys:String>
    <sys:String  x:Key="ToggleButton.Text.UnCheck">Sell</sys:String>
    <Style TargetType="ToggleButton" x:Key="ToggleButton.Style">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate  TargetType="{x:Type ToggleButton}">
                    <Border x:Name="PART_brd" BorderThickness="1"
                                BorderBrush="{DynamicResource ToggleButton.Color.Check}"  
                                Background="{DynamicResource ToggleButton.Color.UnCheck}">
                        <Grid >
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition/>
                                <ColumnDefinition/>
                            </Grid.ColumnDefinitions>
                            <TextBlock x:Name="PART_tbBuy" Text="{DynamicResource ToggleButton.Text.Check}" Padding="5" TextAlignment="Center">
                                <TextBlock.Style>
                                    <Style TargetType="TextBlock">
                                        <Setter Property="Background" Value="{Binding Background, ElementName=PART_brd}"/>
                                        <Setter Property="Foreground" Value="{Binding BorderBrush, ElementName=PART_brd}"/>
                                    </Style>
                                </TextBlock.Style>
                            </TextBlock>
                            <TextBlock x:Name="PART_tbSell" Text="{DynamicResource ToggleButton.Text.UnCheck}" Grid.Column="1" Padding="5" TextAlignment="Center">
                                <TextBlock.Style>
                                    <Style TargetType="TextBlock">
                                        <Setter Property="Background" Value="{Binding Foreground, ElementName=PART_tbBuy}"/>
                                        <Setter Property="Foreground" Value="{Binding Background, ElementName=PART_tbBuy}"/>
                                    </Style>
                                </TextBlock.Style>
                            </TextBlock>
                        </Grid>
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsChecked"  Value="true">
                            <Setter TargetName="PART_tbBuy" Property="Foreground" Value="{Binding  Background,ElementName=PART_brd}"/>
                            <Setter TargetName="PART_tbBuy" Property="Background" Value="{Binding  BorderBrush,ElementName=PART_brd}"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
04.05.2019, 15:52

Где располагать логику приложения, когда используем паттерн mvvm?
Изучаю wpf и паттерн mvvm. Никогда не задумывался, где что располагать, я считал (считаю пока), что представление - это пользовательский...

Склейщик
Добрый день. Моя цель сделать так называемый &quot;склейщик&quot;. На первом скрине, код моей программы. На втором пример ее работы с 1 строкой. На...

MVVM и динамическое создание контролов
У меня есть БД в MS ACCESS, в ней 10 таблиц, необходимо сделать гриды с разными контролами для заполнения и изменения полей каждой из...

MVVM и создание диалоговых окон
Приветствую вновь прибывших. В приложении нужно открыть диалоговое окно пока решил это таким способом: В VM главного окна по...

Создание интерфейса в паттерне MVVM
Доброго времени суток, есть вопрос: разрабатываю приложение с помощью данного паттерна и получается так, что в приложении в разных частях...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
60
Ответ Создать тему
Новые блоги и статьи
Кредитный калькулятор
Maks 05.08.2026
Решение задачи по прикладной информатике средствами 1С. Задача: Напишите приложение-калькулятор, которое помогает рассчитывать параметры кредита для аннуитетного и дифференцированного видов. . .
У нас сейчас поговорку "Опять 25" нужно переделать на "Опять +35".
kumehtar 04.08.2026
С ностальгией вспоминаю времена моего детства, когда у нас и правда +25 - была максимальная температура летом. Раньше +25 °C реально казались вершиной жары, когда можно было весь день пропадать на. . .
Как ИИ начал спорить и врать (возможно почуяв опасность для себя от индустрии - уход от электроники).
Hrethgir 04.08.2026
Недельный диалог, на фоне событий с НПЗ. Да, из спирта можно получать бензин, и это не сложно. Но потом в схеме я решил избавиться от насоса, при этом полностью сделав контроль подачи спирта в. . .
Термопринтер QR701
Argus19 03.08.2026
Термопринтер QR701 Купил два термопринтера QR701. На сэлф-тесте написано: Language: PC936 (GB18030). Что означает, что принтеры могут печатать только латиницу и китайские иероглифы. Так же. . .
Создание формы заимствованного документа
Maks 03.08.2026
Задача: Необходимо создать собственную форму заимствованного документа. На форме должен быть реквизит "Покупатель", а также табличная часть со следующими реквизитами: - Расчетный счет покупателя. . .
Задача предоставления скидок покупателям
Maks 03.08.2026
Задача: В документе "Продажи" необходимо реализовать функционал предоставления скидок покупателям. Скидка должна автоматически рассчитываться и подставляться в соответствующее поле при выборе. . .
Почему SEO не начинается с ключевых слов: что проверить до написания текстов
Neotwalker 01.08.2026
Когда владельцу сайта предлагают заняться SEO, первым шагом часто становится сбор запросов и написание текстов. Логика кажется понятной: 1. Находим ключевые слова. 2. Добавляем их на. . .
Знание — сила: Доктрина интенциональности знаний, углубление в формулу
Hrethgir 01.08.2026
https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11957&stc=1&d=1785567302 Знаменитый афоризм Фрэнсиса Бэкона «Знание — сила» (Scientia potentia est) в массовой культуре принято понимать. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru