Форум программистов, компьютерный форум, киберфорум
C#: WPF, UWP и Silverlight
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.70/43: Рейтинг темы: голосов - 43, средняя оценка - 4.70
Модератор
 Аватар для TanaTiX
2939 / 1800 / 180
Регистрация: 19.02.2011
Сообщений: 6,556

Пытаюсь понять идеологию MVVM

25.02.2020, 19:51. Показов 10363. Ответов 123
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
По предыдущему опыту (не C#) активно использовал MVC. Теперь пытаюсь понять идеологию MVVM. Не могу четко придумать, где должен быть контроллер или его аналог. Сейчас сижу, "курю" мануалы, пытаюсь осознать...[/OFF]
0
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
25.02.2020, 19:51
Ответы с готовыми решениями:

Пытаюсь разобраться с WPF и MVVM и создать приложение
Всем доброе время суток и всех с праздником! Пытаюсь разобраться с WPF и MVVM Фаил MainWindow.xaml <Window...

Пытаюсь понять комбинаторику.Не могу понять какую формулу использовать
Добрый день. Уже второй день бьюсь над комбинаторикой. Проблема стоит в том, что не могу понять, какую формулу нужно...

Пытаюсь понять, не получается
По запросу - Магазины Ярославля 4-9 места занимают какие-то левые сайты, причем в описании присутствует название моего сайта - Магазины...

123
Модератор
 Аватар для TanaTiX
2939 / 1800 / 180
Регистрация: 19.02.2011
Сообщений: 6,556
30.05.2020, 12:39  [ТС]
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от Элд Хасп Посмотреть сообщение
настройки ячейки в конвертере
Правильней же такое править в xaml, а не в CB? Как это можно реализовать? Создавать отдельный элемент для "квадратика"?
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Не уверен в правильности общего подхода
Ведь чем меньше CB, тем лучше. Этот момент частично перекликается с предыдущим.
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Не получается вписать корректно полученный результат
Это самый главный пункт. Как бы хотелось. Я создаю превью для игрового поля в кастомном элементе. Далее помещаю весь этот элемент в некий контейнер
XML
1
2
3
<Grid Grid.Row="1">
                                <local:PreviewGameField ap:FieldPreviewAP.Cells="{Binding Cells}" Grid.Row="1"  HorizontalContentAlignment="Center" VerticalContentAlignment="Center"/>
                            </Grid>
При этом картинка при необходимости сжимается до размера контейнера, при необходимости увеличивается, подстраиваясь под его размер, центруется по горизонтали и вертикали.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,175
Записей в блоге: 2
30.05.2020, 12:45
Цитата Сообщение от TanaTiX Посмотреть сообщение
Правильней же такое править в xaml, а не в CB? Как это можно реализовать? Создавать отдельный элемент для "квадратика"?
Я пока ни как не могу понять в целом, что хочешь сделать.

В начале по коду, вроде, была обработка CellVM.

А по скринам - тома просто квадратики двух разных типов.

Просто покажи на каком-то рисунки, что хочешь сделать.
И из каких данных получить эти рисунки.
0
Модератор
 Аватар для TanaTiX
2939 / 1800 / 180
Регистрация: 19.02.2011
Сообщений: 6,556
30.05.2020, 22:19  [ТС]
Модифицировал немного код:
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
<local:BaseAdditionalUCPage x:Class="View.FirstScreenView"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:vm="clr-namespace:ViewModel;assembly=ViewModel"
            xmlns:local="clr-namespace:View"
            xmlns:ap="clr-namespace:CustomControlLibrary;assembly=CustomControlLibrary"
            mc:Ignorable="d"
            d:DesignHeight="450" d:DesignWidth="800">
    <d:BaseAdditionalUCPage.DataContext>
        <vm:GameListVM/>
    </d:BaseAdditionalUCPage.DataContext>
 
    <local:BaseAdditionalUCPage.Resources>
        
        <local:IconConverter x:Key="IconConverter"/>
        
        <SolidColorBrush Color="#58A0E2" x:Key="Title.Background" />
        <LinearGradientBrush x:Key="Window.Background" StartPoint="0,0" EndPoint="0,1">
            <GradientStop Color="#58A0E2" Offset="0.0" />
            <GradientStop Color="#417669" Offset="1.0" />
 
        </LinearGradientBrush>
        
        <Style x:Key="FocusVisual">
            <Setter Property="Control.Template">
                <Setter.Value>
                    <ControlTemplate>
                        <Rectangle Margin="2" StrokeDashArray="1 2" SnapsToDevicePixels="true" StrokeThickness="1" Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
        <SolidColorBrush x:Key="ScrollBar.Static.Background" Color="#F0F0F0"/>
        <SolidColorBrush x:Key="ScrollBar.Static.Border" Color="#F0F0F0"/>
        <SolidColorBrush x:Key="ScrollBar.Static.Glyph" Color="#606060"/>
        <SolidColorBrush x:Key="ScrollBar.Static.Thumb" Color="#CDCDCD"/>
        <SolidColorBrush x:Key="ScrollBar.MouseOver.Background" Color="#DADADA"/>
        <SolidColorBrush x:Key="ScrollBar.MouseOver.Border" Color="#DADADA"/>
        <SolidColorBrush x:Key="ScrollBar.MouseOver.Glyph" Color="#000000"/>
        <SolidColorBrush x:Key="ScrollBar.MouseOver.Thumb" Color="#A6A6A6"/>
        <SolidColorBrush x:Key="ScrollBar.Pressed.Background" Color="#606060"/>
        <SolidColorBrush x:Key="ScrollBar.Pressed.Border" Color="#606060"/>
        <SolidColorBrush x:Key="ScrollBar.Pressed.Thumb" Color="#606060"/>
        <SolidColorBrush x:Key="ScrollBar.Pressed.Glyph" Color="#FFFFFF"/>
        <SolidColorBrush x:Key="ScrollBar.Disabled.Background" Color="#F0F0F0"/>
        <SolidColorBrush x:Key="ScrollBar.Disabled.Border" Color="#F0F0F0"/>
        <SolidColorBrush x:Key="ScrollBar.Disabled.Glyph" Color="#BFBFBF"/>
        
        <Style x:Key="ScrollBarThumbVertical" TargetType="{x:Type Thumb}">
            <Setter Property="OverridesDefaultStyle" Value="true"/>
            <Setter Property="IsTabStop" Value="false"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Thumb}">
                        <Rectangle x:Name="rectangle" Fill="{StaticResource ScrollBar.Static.Thumb}" Height="{TemplateBinding Height}" SnapsToDevicePixels="True" Width="{TemplateBinding Width}"/>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsMouseOver" Value="true">
                                <Setter Property="Fill" TargetName="rectangle" Value="{StaticResource ScrollBar.MouseOver.Thumb}"/>
                            </Trigger>
                            <Trigger Property="IsDragging" Value="true">
                                <Setter Property="Fill" TargetName="rectangle" Value="{StaticResource ScrollBar.Pressed.Thumb}"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
        
        <Style x:Key="CustomScrollBar" TargetType="{x:Type ScrollBar}">
            <Setter Property="Stylus.IsPressAndHoldEnabled" Value="false"/>
            <Setter Property="Stylus.IsFlicksEnabled" Value="false"/>
            <Setter Property="Background" Value="{StaticResource ScrollBar.Static.Background}"/>
            <Setter Property="BorderBrush" Value="{StaticResource ScrollBar.Static.Border}"/>
            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
            <Setter Property="BorderThickness" Value="1,0"/>
            <Setter Property="Width" Value="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}"/>
            <Setter Property="MinWidth" Value="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ScrollBar}">
                        <Grid x:Name="Bg" SnapsToDevicePixels="true">
                            <Border Background="{TemplateBinding Background}" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}" Grid.Row="1"/>
                            
                            <Track x:Name="PART_Track" IsEnabled="{TemplateBinding IsMouseOver}" IsDirectionReversed="true" Grid.Row="1">
                                
                                <Track.Thumb>
                                    <Thumb Style="{StaticResource ScrollBarThumbVertical}"/>
                                </Track.Thumb>
                            </Track>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            
        </Style>
        <Style x:Key="CustomScroll" TargetType="{x:Type ScrollViewer}">
            <Setter Property="OverridesDefaultStyle" Value="True"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ScrollViewer}">
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition/>
                                <ColumnDefinition Width="Auto"/>
                            </Grid.ColumnDefinitions>
                            <ScrollContentPresenter Grid.Column="0"/>
                            <ScrollBar Style="{DynamicResource CustomScrollBar}" x:Name="PART_VerticalScrollBar" Grid.Column="1" MinWidth="10" Maximum="{TemplateBinding ScrollableHeight}" Opacity="0.5" ViewportSize="{TemplateBinding ViewportHeight}" Value="{TemplateBinding VerticalOffset}" Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}" Width="10"/>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
 
    </local:BaseAdditionalUCPage.Resources>
 
 
 
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="auto"/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Label Grid.Row="0" Content="Crazy Knight" FontFamily="Whimsy TT" HorizontalAlignment="Stretch" HorizontalContentAlignment="Center" FontSize="30" FontWeight="Bold" Background="{Binding Mode=OneWay, Source={StaticResource Title.Background}}"/>
 
        <Rectangle Grid.Row="1" Fill="{Binding Mode=OneWay, Source={StaticResource Window.Background}}"/>
 
        <ItemsControl Grid.Row="1" ItemsSource="{Binding Games}">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Button Margin="20">
                        <!--<Label Width="250" Height="200" Content="{Binding Title}"/>-->
                        <Grid x:Name="ImageContainer" Width="250" Height="300" IsEnabled="False">
                            <Grid.RowDefinitions>
                                <RowDefinition Height="auto"/>
                                <RowDefinition/>
                            </Grid.RowDefinitions>
                            <Label Grid.Row="0" Background="#37648E" Content="{Binding Title}" x:Name="TitleBlock" Height="30" FontSize="20" FontWeight="Bold" HorizontalContentAlignment="Center" FontFamily="Tahoma"/>
                            <Grid Grid.Row="1" x:Name="PreviewImageContainer">
                                <local:PreviewGameField ap:FieldPreviewAP.Width="250" ap:FieldPreviewAP.Height="200" ap:FieldPreviewAP.Cells="{Binding Cells}" Grid.Row="1"  HorizontalContentAlignment="Center" VerticalContentAlignment="Center"/>
                                <!--<local:PreviewGameField ap:FieldPreviewAP.Width="{Binding ElementName=PreviewImageContainer, Path=Width}" ap:FieldPreviewAP.Height="200" ap:FieldPreviewAP.Cells="{Binding Cells}" Grid.Row="1"  HorizontalContentAlignment="Center" VerticalContentAlignment="Center"/>-->
                            </Grid>
                        </Grid>
                    </Button>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
            <ItemsControl.ItemsPanel >
                <ItemsPanelTemplate>
                    <WrapPanel/>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.Template>
                <ControlTemplate>
                    <ScrollViewer Style="{DynamicResource CustomScroll}">
                        <ItemsPresenter HorizontalAlignment="Center"/>
                    </ScrollViewer>
                </ControlTemplate>
            </ItemsControl.Template>
        </ItemsControl>
    </Grid>
</local:BaseAdditionalUCPage>
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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Threading;
using View;
using ViewModel;
 
namespace CustomControlLibrary
{
    public class FieldPreviewAP
    {
 
        public static double GetWidth(DependencyObject obj)
        {
            return (double)obj.GetValue(WidthProperty);
        }
 
        public static void SetWidth(DependencyObject obj, double value)
        {
            obj.SetValue(WidthProperty, value);
        }
 
        // Using a DependencyProperty as the backing store for Width.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty WidthProperty =
            DependencyProperty.RegisterAttached("Width", typeof(double), typeof(FieldPreviewAP), new PropertyMetadata(0.0));
 
        public static double GetHeight(DependencyObject obj)
        {
            return (double)obj.GetValue(HeightProperty);
        }
 
        public static void SetHeight(DependencyObject obj, double value)
        {
            obj.SetValue(HeightProperty, value);
        }
 
        // Using a DependencyProperty as the backing store for Height.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty HeightProperty =
            DependencyProperty.RegisterAttached("Height", typeof(double), typeof(FieldPreviewAP), new PropertyMetadata(0.0));
 
        public static IEnumerable<CellVM> GetCells(DependencyObject obj)
        {
            return (IEnumerable<CellVM>)obj.GetValue(CellsProperty);
        }
 
        public static void SetCells(DependencyObject obj, object value)
        {
            obj.SetValue(CellsProperty, value);
        }
 
        // Using a DependencyProperty as the backing store for Cells.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty CellsProperty =
            DependencyProperty.RegisterAttached("Cells", typeof(object), typeof(FieldPreviewAP), new PropertyMetadata(0, OnFieldChange));
 
        private static void OnFieldChange(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
 
            //d.Dispatcher.BeginInvoke(new Action(() => MessageBox.Show(GetWidth(d).ToString())));
 
            if (!(d is UserControl preview && preview.Content is Grid grid)) throw new ArgumentException("Must be a grid inside UserControl", nameof(d));
            if (!(e.NewValue is IEnumerable<CellVM> cells)) throw new ArgumentException("Must be a IEnumerable<CellVM>", nameof(d));
            //MessageBox.Show(arr.Count().ToString());
            //throw new NotImplementedException();
            int maxRow = 0;
            int maxColumn = 0;
            const double padding = 2.0;
            double size;
            foreach (CellVM item in cells)
            {
                maxColumn = (item.Column > maxColumn) ? item.Column : maxColumn;
                maxRow = (item.Row > maxRow) ? item.Row : maxRow;
            }
 
            size = GetWidth(d) / (maxColumn + 1);
            if (GetHeight(d) / (maxRow +1) < size)
            {
                size = GetHeight(d) / (maxColumn + 1);
            }
            //if (size - padding <= 0) return;
            for (int i = 0; i <= maxRow; i++)
            {
                grid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(size) });
            }
            for (int i = 0; i <= maxColumn; i++)
            {
                grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(size) });
            }
            foreach (CellVM item in cells)
            {
                PreviewBlock border = new PreviewBlock() { Width = size - padding, Height = size - padding };
                grid.Children.Add(border);
                Grid.SetRow(border, item.Row);
                Grid.SetColumn(border, item.Column);
            }
        }
    }
}
Маленький квадратик все же вынес в отдельный xml. Правда не совсем понимаю, нет ли тут лишнего чего? Удаление блока UserControl приводит к ошибке.
XML
1
2
3
4
5
6
7
8
9
10
11
12
<UserControl x:Class="View.PreviewBlock"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:View"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <Border Background="#24656C">
            
    </Border>
</UserControl>
Особенностью стало то, что в AttachedProperties можно добавлять сразу несколько свойств - в результате я передаю размер контейнера для рассчета размера ячеек - все работает, что не получалось. Но попытался настроить в AttachedProperty систему Binding - значение не передается.
XML
1
<local:PreviewGameField ap:FieldPreviewAP.Width="{Binding ElementName=PreviewImageContainer, Path=Width}" ap:FieldPreviewAP.Height="200" ap:FieldPreviewAP.Cells="{Binding Cells}" Grid.Row="1"  HorizontalContentAlignment="Center" VerticalContentAlignment="Center"/>
В этом куске Width не передает значение - в класс ap:FieldPreviewAP передается 0, что вызывает ошибку. Но если передавать непосредственно значение, то все хорошо. Возможно это как-то настроить. что бы значение программа считывала с одного места?
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,175
Записей в блоге: 2
30.05.2020, 23:47
Цитата Сообщение от TanaTiX Посмотреть сообщение
В этом куске Width не передает значение - в класс ap:FieldPreviewAP передается 0, что вызывает ошибку. Но если передавать непосредственно значение, то все хорошо. Возможно это как-то настроить. что бы значение программа считывала с одного места?
При объявлении AP-свойства не задан режим привязки по умолчанию.
Если он не задаётся, то режим OneWay.

Добавлено через 3 минуты
Или наоборот из источника в AP свойство значение не передаётся?

Если так, то скорее всего local:PreviewGameField.Width=0.
Для определения размера во время исполнения нужны свойства Actual....
1
Модератор
 Аватар для TanaTiX
2939 / 1800 / 180
Регистрация: 19.02.2011
Сообщений: 6,556
31.05.2020, 15:44  [ТС]
Actual тоже не помог. Принято решение дабы не усложнять такой мелочью проект задать жесткие размеры - в данном случае это вполне допустимый компромисс.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,175
Записей в блоге: 2
31.05.2020, 16:07
Цитата Сообщение от TanaTiX Посмотреть сообщение
Actual тоже не помог.
Может происходит перекрытие контейнеров - надо разбирать визуальное дерево.
Без этого ничего сказать не могу.
0
Модератор
 Аватар для TanaTiX
2939 / 1800 / 180
Регистрация: 19.02.2011
Сообщений: 6,556
04.06.2020, 23:14  [ТС]
В процессе выяснения причин выяснилось следующее. (код как есть с комментированными участками и прочим лишним мусором, за что извиняюсь)
При уменьшении размера контейнера часть превью скрывается, но если размер контейнера, к примеру 200*200, то все показывается правильно.
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
using Microsoft.VisualBasic.CompilerServices;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Threading;
using View;
using ViewModel;
 
namespace CustomControlLibrary
{
    public class FieldPreviewAP
    {
 
 
 
        public static double GetWidth(DependencyObject obj)
        {
            return (double)obj.GetValue(WidthProperty);
        }
 
        public static void SetWidth(DependencyObject obj, double value)
        {
            obj.SetValue(WidthProperty, value);
        }
 
        // Using a DependencyProperty as the backing store for Width.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty WidthProperty =
            DependencyProperty.RegisterAttached("Width", typeof(double), typeof(FieldPreviewAP), new PropertyMetadata(0.0));
 
 
 
 
        public static double GetHeight(DependencyObject obj)
        {
            return (double)obj.GetValue(HeightProperty);
        }
 
        public static void SetHeight(DependencyObject obj, double value)
        {
            obj.SetValue(HeightProperty, value);
        }
 
        // Using a DependencyProperty as the backing store for Height.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty HeightProperty =
            DependencyProperty.RegisterAttached("Height", typeof(double), typeof(FieldPreviewAP), new PropertyMetadata(0.0));
 
 
 
 
 
 
        public static IEnumerable<CellVM> GetCells(DependencyObject obj)
        {
            return (IEnumerable<CellVM>)obj.GetValue(CellsProperty);
        }
 
        public static void SetCells(DependencyObject obj, object value)
        {
            obj.SetValue(CellsProperty, value);
        }
 
        // Using a DependencyProperty as the backing store for Cells.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty CellsProperty =
            DependencyProperty.RegisterAttached("Cells", typeof(object), typeof(FieldPreviewAP), new PropertyMetadata(0, OnFieldChange));
 
        private static void OnFieldChange(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
 
            //d.Dispatcher.BeginInvoke(new Action(() => MessageBox.Show(GetWidth(d).ToString())));
 
            if (!(d is UserControl preview && preview.Content is Grid grid)) throw new ArgumentException("Must be a grid inside UserControl", nameof(d));
            if (!(e.NewValue is IEnumerable<CellVM> cells)) throw new ArgumentException("Must be a IEnumerable<CellVM>", nameof(d));
            //MessageBox.Show(arr.Count().ToString());
            //throw new NotImplementedException();
            int maxRow = 0;
            int maxColumn = 0;
            const double padding = 2.0;
            double size;
            foreach (CellVM item in cells)
            {
                maxColumn = (item.Column > maxColumn) ? item.Column : maxColumn;
                maxRow = (item.Row > maxRow) ? item.Row : maxRow;
            }
 
            size = GetWidth(d) / (maxColumn);
            if (GetHeight(d) / (maxRow) < size)
            {
                size = GetHeight(d) / (maxRow);
            }
            //if (size - padding <= 0) return;
            for (int i = 0; i <= maxRow; i++)
            {
                grid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(size) });
            }
            for (int i = 0; i <= maxColumn; i++)
            {
                grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(size) });
            }
            Debug.Print("**************************************************");
            foreach (CellVM item in cells)
            {
                PreviewBlock border = new PreviewBlock() { Width = size - padding, Height = size - padding };
                grid.Children.Add(border);
                Grid.SetRow(border, item.Row);
                Grid.SetColumn(border, item.Column);
                Debug.Print(item.Row+" "+item.Column);
            }
            Debug.Print("" + (size * maxRow) + " " + grid.Height + " " + grid.Width);
        }
    }
}
Так вот, в последних строках код Debug.Print("" + (size * maxRow) + " " + grid.Height + " " + grid.Width); выдает на значение высоты и ширины grid "не число". Думается мне, что в этом причина не правильного отображения превью.
Или с чем еще может быть связано?
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,175
Записей в блоге: 2
04.06.2020, 23:28
Цитата Сообщение от TanaTiX Посмотреть сообщение
Думается мне, что в этом причина не правильного отображения превью.
Если элемент не попадает в область визуализации и у него нет явно заданных размеров, то так и должно работать.
1
Модератор
 Аватар для TanaTiX
2939 / 1800 / 180
Регистрация: 19.02.2011
Сообщений: 6,556
05.06.2020, 00:10  [ТС]
Элд Хасп, это помогло. Проблема оказалась в неверных расчетах.

Сейчас стал смотреть изменения в проекте и нашел файл launchSettings.json в папке Properties основного проекта. Откуда это и зачем?
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,175
Записей в блоге: 2
05.06.2020, 01:55
Цитата Сообщение от TanaTiX Посмотреть сообщение
Сейчас стал смотреть изменения в проекте и нашел файл launchSettings.json в папке Properties основного проекта. Откуда это и зачем?
Точно не знаю.
Что-то с настройками проекта.
0
Модератор
 Аватар для TanaTiX
2939 / 1800 / 180
Регистрация: 19.02.2011
Сообщений: 6,556
05.06.2020, 21:17  [ТС]
При разработке нового приложения все шло хорошо до момента реализации интерфейса ICommand. Вместе с Элд Хасп-ом, была реализация в проекте .Net FrameWork, но в Core такой подход не работает. Кто может подсказать по правильной реализации команд в приложении Core? Может в коре вообще другой подход используется?
Попробовал поискать, но такое впечатление, что ищу не в том направлении: кидает или на откровенную чушь, или на фреймворковские проекты. Очень надеюсь на помощь.

Добавлено через 30 минут
Как оказалось файл проекта (*.csproj) нужно поменять таким образом:
XML
1
2
3
4
5
6
7
8
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
 
  <PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
    <UseWPF>true</UseWPF>
  </PropertyGroup>
 
</Project>
1
Модератор
 Аватар для TanaTiX
2939 / 1800 / 180
Регистрация: 19.02.2011
Сообщений: 6,556
08.06.2020, 00:30  [ТС]
Появилась непонятная проблема.
На каком-то этапе разработки в окне xaml вместо картинки выдает ошибку:
System.NullReferenceException
Ссылка на объект не указывает на экземпляр объекта.
в Microsoft.VisualStudio.DesignTools.Marku p.DocumentModel.DocumentCompositeNode.Ge tBestConstructor(IConstructorArgumentNod eCollection& constructorArguments)
в Microsoft.VisualStudio.DesignTools.Runti meHost.InstanceBuilders.Core.CoreInstanc eBuilder.CreateCompositeNodeInstance(IIn stanceBuilderContext context, LiveNodeProxy liveNode, DocumentCompositeNode documentNode, String typeName)
в Microsoft.VisualStudio.DesignTools.Runti meHost.InstanceBuilders.Core.CoreInstanc eBuilder.Instantiate(IInstanceBuilderCon text context, LiveNodeProxy liveNode)
в Microsoft.VisualStudio.DesignTools.Runti meHost.InstanceBuilders.Core.CoreInstanc eBuilder.InstantiateProperty(IInstanceBu ilderContext context, IInstanceBuilder childBuilder, LiveNodeProxy child, IProperty property)
в Microsoft.VisualStudio.DesignTools.Runti meHost.InstanceBuilders.Core.CoreInstanc eBuilder.UpdateProperty(IInstanceBuilder Context context, DocumentCompositeNode parentNode, DocumentNode oldNode, DocumentNode newNode, IProperty property)
в Microsoft.VisualStudio.DesignTools.Runti meHost.InstanceBuilders.Wpf.FrameworkEle mentBuilder.UpdatePropertyInternal(IInst anceBuilderContext context, DocumentCompositeNode parentNode, DocumentNode oldNode, DocumentNode newNode, IProperty property)
в Microsoft.VisualStudio.DesignTools.Runti meHost.InstanceBuilders.Wpf.FrameworkEle mentBuilder.UpdateProperty(IInstanceBuil derContext context, DocumentCompositeNode parentNode, DocumentNode oldNode, DocumentNode newNode, IProperty property)
в Microsoft.VisualStudio.DesignTools.Runti meHost.InstanceBuilders.InstanceBuilderU tility.UpdatePropertyOrEvent(IInstanceBu ilder builder, IInstanceBuilderContext context, DocumentCompositeNode parentNode, DocumentNode oldNode, DocumentNode newNode, IProperty property)
в Microsoft.VisualStudio.DesignTools.Runti meHost.InstanceBuilders.Core.CoreInstanc eBuilder.BuildProperties(IInstanceBuilde rContext context, LiveNodeProxy liveNode, DocumentCompositeNode compositeNode, BuildOrder buildOrder)
в Microsoft.VisualStudio.DesignTools.Runti meHost.InstanceBuilders.Wpf.FrameworkEle mentBuilder.BuildProperties(IInstanceBui lderContext context, LiveNodeProxy liveNode, DocumentCompositeNode compositeNode, BuildOrder buildOrder)
в Microsoft.VisualStudio.DesignTools.Runti meHost.InstanceBuilders.Core.CoreInstanc eBuilder.Initialize(IInstanceBuilderCont ext context, LiveNodeProxy liveNode, BuildOrder buildOrder)
в Microsoft.VisualStudio.DesignTools.Runti meHost.InstanceBuilders.Core.RebuildProp ertyBuilder.Initialize(IInstanceBuilderC ontext context, LiveNodeProxy liveNode, BuildOrder buildOrder)
в Microsoft.VisualStudio.DesignTools.Surfa ceDesigner.Documents.SurfaceIsolation.De signerInstanceManager.EnsureInstanceBuil derActions(ISurfaceProcessDocument surfaceDocument)
в Microsoft.VisualStudio.DesignTools.Surfa ceDesigner.Documents.SurfaceIsolation.De signerInstanceManager.MakeCreateDocument Info(ISurfaceProcessDocument document, Boolean includeInstanceBuildingActions)
в Microsoft.VisualStudio.DesignTools.Surfa ceDesigner.Documents.SurfaceIsolation.De signerInstanceManager.HandleDocumentBuil dingActionsRequest(GetDocumentBuildingAc tionsRequest request)
--- Конец трассировка стека из предыдущего расположения, где возникло исключение ---
в Microsoft.VisualStudio.Telemetry.Windows ErrorReporting.WatsonReport.GetClrWatson ExceptionInfo(Exception exceptionObject)
Перезагрузка, пересборка, пере-всё проблему не решает. Код в этом или другом любом заинтересованном месте не менял. Ошибку не показывает. Проект при этом компилируется и работает без ошибок.

Где появился этот Null и как от него избавиться для комфортной работы не понятно.
0
Модератор
 Аватар для TanaTiX
2939 / 1800 / 180
Регистрация: 19.02.2011
Сообщений: 6,556
08.06.2020, 01:36  [ТС]
Опытным путем выяснилось, что ошибка где-то вокруг
XML
1
2
3
<d:BaseAdditionalUCPage.DataContext>
        <vm:GameListVM/>
    </d:BaseAdditionalUCPage.DataContext>
По крайней мере при комментировании этого блока превью xaml оживает. Поиск продолжаю.

Добавлено через 3 минуты
В GameListVM добавлял конструктор с параметром - из-за этого возникла ошибка. Добавил еще один конструктор без параметра - все работает штатно.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,175
Записей в блоге: 2
08.06.2020, 08:45
Цитата Сообщение от TanaTiX Посмотреть сообщение
Опытным путем выяснилось, что ошибка где-то вокруг
Это Ошибка связана с отсутствием у VM определения режима Времени Разработки.

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

Решается это типовыми вариантами:
  • Первый. Так как в XAML в основном используется безпараметрический конструктор, то при обращении к нему считается, что VM создаётся в Режиме Разработки.
    А если идёт обращение к параметрическому конструктору - Режим Исполнения.
  • Второй. Определяется DesignMode через параметры Application. Такой подход реализован, например, в MVVMLight.
1
Модератор
 Аватар для TanaTiX
2939 / 1800 / 180
Регистрация: 19.02.2011
Сообщений: 6,556
05.09.2020, 17:49  [ТС]
А как идеологически правильно создавать команды и окна? Т.е. есть кнопка, по клику на нее появляется окошко с кнопкой закрыть. В этом окне что-то происходит, должна быть связь с моделью. После всех действий окно закрывается, модель изменяется.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,175
Записей в блоге: 2
05.09.2020, 18:42
Цитата Сообщение от TanaTiX Посмотреть сообщение
А как идеологически правильно создавать команды и окна?
Это зависит от задачи.

Создаваемое окно может быть ни как не связано с Данными.
Допустим, окно About (О приложении).
У него свои данные получаемые из информации сборки и эти данные ни как не связанны с Моделью для основной логики.
Такое окно можно, вообще, создать модальным диалогом в клике кнопки.

Другая задача: требуется в модальном окне ввести/изменить какие-то данные.
Допустим, данные человеке.
Здесь можно использовать делегат обратного вызова передаваемый в конструктор VM.
Примерно с такой сигнатурой:
C#
1
public delegate bool? EditPersonHandler(Person person);
В параметре передаются данные для редактирования, а возвращает метод true - если редактирование надо сохранить.
Метод реализуется по месту создания ViewModel. Обычно в App.
В теле метода модельный вызов окна редактирования с передачей ему полученного person и возвратом модального результата.

Есть ещё множество вариантов реализаций.
В том числе с использованием Локаторов, Шин Сообщений Передача данных между Окнами, между VM, Шина Сообщений, Локатор.

Для определённости нужна конкретная задача, детали её реализации.
1
Модератор
 Аватар для TanaTiX
2939 / 1800 / 180
Регистрация: 19.02.2011
Сообщений: 6,556
05.09.2020, 18:50  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Для определённости нужна конкретная задача, детали её реализации.
Конкретно сейчас в окне вводятся данные, которые сохраняются в моделе, что находит отражение во вью. Больше никаких задач.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,175
Записей в блоге: 2
05.09.2020, 19:20
Цитата Сообщение от TanaTiX Посмотреть сообщение
Конкретно сейчас в окне вводятся данные, которые сохраняются в моделе, что находит отражение во вью. Больше никаких задач.
Что за Модель, ViewModel?
Как они свзязаны?
Какие окна? Как они привязаны к VM?
Из каких команд какие диалоги надо открывать?
И т.д., и т.п.

А без этих деталей будет только "сферический конь в вакууме".
0
Модератор
 Аватар для TanaTiX
2939 / 1800 / 180
Регистрация: 19.02.2011
Сообщений: 6,556
05.09.2020, 22:29  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Что за Модель, ViewModel?
просто модель
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Как они свзязаны?
C#
1
2
3
ControlManager manager = new ControlManager(window);
            DataModel model = new DataModel();
            MainVM modelVM = new MainVM(model);
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Какие окна? Как они привязаны к VM?
Не понял вопрос. Обычные окна, экземпляры Window.
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Из каких команд какие диалоги надо открывать?
И т.д., и т.п.
Клик по кнопке приводит к появлению окна. В этом окне ряд действий, суть которых в том, что на основании ряда параметров (редактируются в окне) запускается метод в моделе по изменению данных модели (да, вот именно так оно и происходит - особенность задачи).
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,175
Записей в блоге: 2
05.09.2020, 22:38
Цитата Сообщение от TanaTiX Посмотреть сообщение
Не понял вопрос. Обычные окна, экземпляры Window.
Как создаются экземпляры окон?
Модальный или обычный показ?
Как передаётся VM в другое окно?
Или у него собственная VM?
Если да, то как она создаётся и связана с общей Моделью.

Вы видите и понимаете своё приложения.
Но по вашим объяснениям совершенно ничего не понятно.

Лучше сделайте какой-то просто пример полезный вам и объясните на нём.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
05.09.2020, 22:38

Основы MVC, пытаюсь понять код
Суть в чем, мне на производственной практике дали задание написать веб-приложение для управления списком сотрудников компании. Ну я его...

Я самоучка, пытаюсь понять квантовый мир
Привет. Я самоучка, пытаюсь понять квантовый мир, но застрял. Просьба ногами не бить. 1. Формула замедления времени не зависит от...

Пытаюсь понять шаблонизатор Handlebars для JavaScript
Привет. Нагуглил вот эту статью: http://getinstance.info/articles/tools/introduction-to-handlebars/ Но у меня самый первый пример...

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

Написать программу в Excel, пытаюсь понять, но не получается
Написать программу сведений о выпускниках университета. Структура исходных данных: шифр студента, фамилия, имя, отчество, год окончания...


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

Или воспользуйтесь поиском по форуму:
120
Ответ Создать тему
Новые блоги и статьи
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр.
Jin X 06.09.2026
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр. Работая с форумом и нейросетями в браузере часто хочется что-то подкорректировать или добавить какого-то функционала. Ниже прикреплён. . .
Программа опроса у.з. расходомера SLS-720F
Argus19 02.09.2026
Программа опроса у. з. расходомера SLS-720F Программа опрашивает один раз в минуту три ультразвуковых расходомера SLS-720F через интерфейс RS-485 по протоколу Modbus RTU. Опрашиваются регистры. . .
Hyper-V: Компьютер должен поддерживать доверенный платформенный модуль 2.0.
Maks 31.08.2026
При установке Windows 11 на виртуальную машину Hyper-V 2-го поколения вылезла такая ошибка: Решение: в параметрах виртуальной машины, в разделе "Безопасность" (Security) активировать флаг. . .
Архитектура биовида Стива в Майнкрафте: Зачем бонобо кубический каннибализм
anaschu 30.08.2026
Кубический Вагинокапитализм в Minecraft: Математический инвариант ОДУ и рок Стивов-бонобо Главная задача разработанной «Модели Всего» — наглядно продемонстрировать наличие системной «судьбы». . .
Оттачиваю умение писать js программы.
russiannick 30.08.2026
Проектом выходного дня стало написание Книги шифров Виженера. Итогом стала версия 200, синий туман. Синий туман назван так, потому что замораживает текст под собой. Нажатие синих кнопок управляют. . .
мат медиц модель 30. презентация проекта
anaschu 27.08.2026
хоп хоп хоп хидахоп, а я кладую))
Как у меня протекала болезнь
zorxor 27.08.2026
Здравствуйте, друзья! Эта запись блога предназначена именно для вас - для моих дорогих друзей, которые знали меня лично. Чтобы ответить на вопрос - а что же со мной произошло на самом деле? Я учился. . .
Нашел вот забавное видео о измерениях. Лучшее что я видел на эту тему
kumehtar 26.08.2026
ILETXiw9bMQ Основная суть и тезисы по измерениям: 0D (Нулевое измерение): точка, не имеющая длины, ширины, высоты или объема. Объект не может перемещаться в 0D. 1D (Первое измерение):. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru