Форум программистов, компьютерный форум, киберфорум
C#: WPF, UWP и Silverlight
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.69/26: Рейтинг темы: голосов - 26, средняя оценка - 4.69
 Аватар для xellan24rus
364 / 296 / 55
Регистрация: 08.04.2020
Сообщений: 1,175

Разделение функционала между слоями MVVM на примере создания простого WPF приложения с БД

10.02.2024, 00:12. Показов 8822. Ответов 182
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Тема создана разделением темы Вывод на печать изображения MVVM


Цитата Сообщение от Элд Хасп Посмотреть сообщение
Вы имеете - некое свойство может иметь значения разных типов (или даже одного типа) и View выводит разные представления для разных значений, то это снимает часть противоречий.
Да про это. например в
XML
1
 <ContentControl Grid.Column="1" Content="{Binding CurrentView}"></ContentControl>
идет привязка к свойству CurrentView, оно же изменяется при переключение RadioButton. То есть от выбранного RadioButton зависит какой контент будет у ContentControl. Получается что представление очень зависимо от свойства CurrentView.

Кликните здесь для просмотра всего текста
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
public class MainWindowVM : ViewModelBase
    {
        public MainWindowVM()
        {
            //Создаём команды
            OpenUserControl1Command = new RelayCommand(OpenUserControl1);
            OpenUserControl2Command = new RelayCommand(OpenUserControl2);
            OpenUserControl3Command = new RelayCommand(OpenUserControl3);
 
            OpenOtherControlCommand = new RelayCommand(OpenOtherControlCommandExecute);
        }
        #region открытие user control
        private object _popupCurrentView;
 
        public object PopupCurrentView
        {
            get => _popupCurrentView;
            set
            {
                _popupCurrentView = value;
                OnPropertyChanged(nameof(PopupCurrentView));
            }
        }
        public ICommand OpenOtherControlCommand { get; private set; }
        public void OpenOtherControlCommandExecute(object obj) => PopupCurrentView = new SelectLangue();
 
        public ICommand CloseOtherControlCommand { get; private set; }
        public void CloseOtherControlCommandExecute(object obj) => PopupCurrentView = null;
        #endregion
 
        private object _currentView;
 
        /// <summary>
        /// ListcurrentView нужен для хранения состояния UserControl. 
        /// Все действия над представлением и изменением контента сохраняются в этой коллекции. 
        /// Если хранить  представление и изменением контента не нужно. Тогда лучше удалить эту коллекцию и связанный с ней метод.
        /// </summary>
        private List<UserControl> ListcurrentView = new();
 
        /// <summary>
        /// Отображание текущего UserContol в ContentControl в окне MainWindow
        /// </summary>
        public object CurrentView
        {
            get => _currentView;
            set
            {
                _currentView = value;
                OnPropertyChanged(nameof(CurrentView));
            }
        }
        #region Команды для отображения UserControl в окне MainWindow
        public ICommand OpenUserControl1Command { get; }
        private void OpenUserControl1(object obj) => CurrentView = GetOrAddUserControl<UserControl1>();
 
        public ICommand OpenUserControl2Command { get; }
        private void OpenUserControl2(object obj) => CurrentView = GetOrAddUserControl<UserControl2>();
 
        public ICommand OpenUserControl3Command { get; }
        private void OpenUserControl3(object obj) => CurrentView = GetOrAddUserControl<UserControl3>();
 
        /// <summary>
        /// Универсальный метод для возвращения UserControl из коллекции
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        private UserControl GetOrAddUserControl<T>() where T : UserControl, new()
        {
            var control = ListcurrentView.Find(c => c.GetType() == typeof(T));
            if (control == null)
            {
                control = new T();
                ListcurrentView.Add(control);
            }
            return control;
        }
        #endregion
    }


Цитата Сообщение от Элд Хасп Посмотреть сообщение
И такое переключение должно быть реализовано с помощью навигатора в View.
Использование сервисов, чтобы узнать об изменение View?
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
10.02.2024, 00:12
Ответы с готовыми решениями:

ASP.NET MVC - разделение функционала между различными view
Добрый день)) Хочу спросить совета. В своем проекте использую MVC + jQuery, чтобы создать функционал в системе, аналогичный тому, что...

WPF MVVM: варианты создания VM с параметрами
Есть обычная ViewModel: public class SomeViewModel { private readonly ILogger logger; private readonly...

WPF нюансы создания проводника и мелочи по MVVM
Здравствуйте. Я только начинаю осваивать WPF и паттерн MVVM, и вот в чём загвостка: 1) Я уже написал визуальное оформление приложения и...

182
Эксперт JavaЭксперт по электроникеЭксперт .NET
 Аватар для wizard41
3460 / 2781 / 575
Регистрация: 04.09.2018
Сообщений: 8,743
Записей в блоге: 3
27.02.2024, 00:02
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от Элд Хасп Посмотреть сообщение
сделать фанатично правильную реализацию MVVM
Ну, "правильнее" от этого она вряд ли станет, а вот внести неясность в умы изучающих паттерн может.
Здесь, я бы сказал, вы пытаетесь сделать так:
Допустим, есть проект "Чайник". В нем есть уровень воды и температура. Оба этих параметра нам нужно контролировать. Не смотря на то, что оба объекта: уровень и температура фактически являются описательными для данного проекта, вы их разносите по разным проектам. И это, с некоторой позиции нормально, т.к. эти проекты могут быть использованы, например, в кофеварке или стиральной машине. Но прямо, это разделение не привносит ясности в саму суть разделения MVVM.
Т.е. связь между ними, согласно паттерну, можно осуществить и в пределах одного решения.
Цитата Сообщение от xellan24rus Посмотреть сообщение
Получается DataBase, Repository туда полностью перенести?
Продолжим с "Чайником"...
Допустим, мы сохраняем параметры уровня и температуры в БД, через какие-то интервалы времени. Сегодня у нас база - MSSQL. Завтра мы передумали, и перешли на Postgres, а через неделю понадобилась MySQL. О-па! Куда это все совать? В Common? Нееет!
Вот тут это могут быть или отдельные проекты типа Провайдеров, каждый со своим функционалом, либо же один отдельный проект со всеми ими. Фактически, возвращаемые данные и запросы к этим БД одинаковы; меняются только строки подключения.
Цитата Сообщение от xellan24rus Посмотреть сообщение
DepencyObject
Этот объект может весьма помешать правильному и полному понимаю. Регистрация свойств происходит "где-то там", и не понятно почему и как Binding в XAML их подхватывает. Своего рода "чит".
0
 Аватар для xellan24rus
364 / 296 / 55
Регистрация: 08.04.2020
Сообщений: 1,175
27.02.2024, 00:11  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Вот здесь зависимость:
Потому что Repository ссылается на DataBase

Добавлено через 41 секунду
Так как этот класс работает напрямую с источником, то у него не получится отобрать ссылку на DataBase

Добавлено через 7 минут
Цитата Сообщение от wizard41 Посмотреть сообщение
отдельные проекты типа Провайдеров
из этого я понял что Repository лучше перенести DataBase так как если я буду менять каждый день бд, то это будет идеальный вариант, так как Бд и реализация команд реализуется в одном решении.
А Common по вышеописанным примерам, описал почему не лучший для объединения. э

Исходя из этого Везде где наследуется интерфейс идёт работа с данными, а данные это бд. Из этого можно задуматься зачем разделять интерфейсы и бд и тем более их реализацию готовых методов. Так как скакать придется по проектам еще больше.

А пример занятный описали.
Цитата Сообщение от wizard41 Посмотреть сообщение
Своего рода "чит".
Я читал про это в мсдн, занятная штука.
0
Эксперт JavaЭксперт по электроникеЭксперт .NET
 Аватар для wizard41
3460 / 2781 / 575
Регистрация: 04.09.2018
Сообщений: 8,743
Записей в блоге: 3
27.02.2024, 00:16
xellan24rus, работа (обязанность) БД - предоставлять данные. Через интерфейс можно VM дать понять - данные какого типа ожидать. Но VM вообще не должна знать, что эти данные выбираются из какой-то БД. Сегодня это БД, завтра json с сервера.
0
 Аватар для xellan24rus
364 / 296 / 55
Регистрация: 08.04.2020
Сообщений: 1,175
27.02.2024, 00:17  [ТС]
Цитата Сообщение от wizard41 Посмотреть сообщение
работа (обязанность) БД - предоставлять данные. Через интерфейс можно VM дать понять - данные какого типа ожидать. Но VM вообще не должна знать, что эти данные выбираются из какой-то БД. Сегодня это БД, завтра json с сервера.
Это реализовано. Чтобы изменить источник достаточно залезть в один класс только.
0
Эксперт JavaЭксперт по электроникеЭксперт .NET
 Аватар для wizard41
3460 / 2781 / 575
Регистрация: 04.09.2018
Сообщений: 8,743
Записей в блоге: 3
27.02.2024, 00:24
xellan24rus, отделить модели от представления - начальный шаг к цели. Второй: выкинуть "сильные" ссылки одного на другое. У тебя сильная ссылка на DataBase.
1
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16164 / 11284 / 2891
Регистрация: 21.04.2018
Сообщений: 33,169
Записей в блоге: 2
27.02.2024, 00:29
Цитата Сообщение от xellan24rus Посмотреть сообщение
Чтобы изменить источник достаточно залезть в один класс только.
Нет.
Изменение источника в вашей реализации приводит в перекомпиляции всех вышестоящих слоёв.
Вы просто этого не замечаете, так как Студия делает это автоматические.
Сделайте связи через сборки, а не через проекты и вы сразу поймёте, то что я с wizard41 пытаемся вам объяснить.
0
 Аватар для xellan24rus
364 / 296 / 55
Регистрация: 08.04.2020
Сообщений: 1,175
27.02.2024, 00:55  [ТС]
Цитата Сообщение от wizard41 Посмотреть сообщение
отделить модели от представления - начальный шаг к цели. Второй: выкинуть "сильные" ссылки одного на другое. У тебя сильная ссылка на DataBase.
Элд Хасп, Но на работу с DataBase у меня ссылается только один проект. А остальное это уже использование типов в решение. Допустим Есть интерфейс и его реализует 10 проектов, стоит изменить всего одно свойство, то придется лезть во все проекты.
К примеру сейчас у ConsoleApp идет зависимость на Repository и у главного проекта такая же зависимость. Так как Repository связан с типами DataBase и реализует нужные интерфейсы, то зависимость идёт только к типам.

Цитата Сообщение от Элд Хасп Посмотреть сообщение
Изменение источника в вашей реализации приводит в перекомпиляции всех вышестоящих слоёв.
Если я поменяю источник, то всё останется прежним. Придется менять всё только в случае если я буду изменять типы, а это может произойти только при изменении интерфейсов.
А на это уже нет никакого решения, если User в ConsoleApp используется, то и в главном проекте он User, если я изменю User на Users то придется лезть в оба проекта. Но так как работа с данными идёт только в одном классе, тот же метод Add, Remove, FirstOrDefault. То не состоит труда изменить бд, на json или xml. Ведь типы останутся прежними.

Добавлено через 4 минуты
И даже если я разделю работу с данными People и Product на разные классы, то при изменение источника мне придется лезть во все эти классы, не говоря уже о дубле кода. Но это позволит сократить ссылки на DataBase, то есть можно меньше обращаться к типам, но не мало важно что при обновлении типа можно заменить разом через поиск, а вот дубли кода придется делать вручную.

Добавлено через 6 минут
И даже если для работы будут разные классы с дублями кода, то ориентироваться в таком приложение сложнее. И так как эти классы будут ссылаться на проект с источником или источник, то эта зависимость всегда будет.
В этом вопросе не вижу выхода какого то, которое сведет правки на минимум. Редактирование дублей кода или же замена типов, сейчас речь идёт об этом.
wizard41, можете посмотреть реализацию на данный момент, я вроде бы всё подчистил лишнее.
0
Эксперт JavaЭксперт по электроникеЭксперт .NET
 Аватар для wizard41
3460 / 2781 / 575
Регистрация: 04.09.2018
Сообщений: 8,743
Записей в блоге: 3
27.02.2024, 01:35
xellan24rus, хоть вопрос адресован Элд Хасп'у, все же вставлю свои 5 копеек:
интерфейс - это контракт, который обязаны соблюдать все, кто наследуется от него. И естественно, если что-то в нем меняется, то эти изменения необходимо отразить и в объектах-наследниках. Поэтому, желательно сразу продумывать то, что в нем будет. Если все же есть некоторые сомнения, то интерфейсы поддерживают различного рода перегрузки и реализации по умолчанию.
Но на данный момент, вроде как, вопрос не о них.

У тебя сейчас получается VM должна знать (знает) о каком-то репозитории, через который(!) получает еще и тип ProductData.
О типе ProductData должен сообщить интерфейс, а выбрать коллекцию ProductData должна модель и передать ее VM.
От куда эта коллекция взялась - VM вообще не должно волновать.

Грубо говоря: ты скрыл от всех реализацию сбора данных, и никто не должен знать как она работает. Может быть она шифрованная и в объекты их преобразует твой супер-алгоритм, который ты никому не хочешь показывать.
Я прихожу со своим окном (VM) и говорю - дай-ка мне свои данные из БД... И тебе придется раскрыть мне добрую половину своих моделей/типов, чтобы мое окно поняло то, что туда летит.

Добавлено через 21 минуту
Цитата Сообщение от xellan24rus Посмотреть сообщение
можете посмотреть реализацию на данный момент
я так, между делом решил включиться, отвлечься т.с. от основной работы. Проект уже разросся до такой степени, что нужно конкретно вникать, но времени столько нет.
На вскидку скажу одно: уж очень все раскидано, что, вероятно, привносит "кашу" в понимание. Там, смотрю, еще EF участвует со своими DbSet'ами.
Я, однажды, уже прошел в некоторой степени "муки ада" понимания mvvm шаблона, впрочем, как и Элд Хасп, поэтому, нам, вероятно проще в голове выстроить связи "на лету". А тем, кто только начинает - лучше "прочувствовать" это все руками, не прибегая к помощи фреймворков.
1
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16164 / 11284 / 2891
Регистрация: 21.04.2018
Сообщений: 33,169
Записей в блоге: 2
27.02.2024, 10:11
Цитата Сообщение от xellan24rus Посмотреть сообщение
Допустим Есть интерфейс и его реализует 10 проектов, стоит изменить всего одно свойство, то придется лезть во все проекты.
Это норльмально.
Как написал выше wizard41: интерфейс - это контракт. Изменение контракта - естественно повлечёт изменение работы всех принявших этот контракт.

Но DataBase - это не контракт, а его реализация.
Например, вы захотели просто изменить название БД:
C#
23
24
            // optionsBuilder.UseSqlite(@$"Data Source={path}\\Data Base.db");
            optionsBuilder.UseSqlite(@$"Data Source={path}\\BestBD.db");
То, что это приведёт к перекомпиляции сборки РЕАЛИЗАЦИИ - это нормально.
Но при сильных ссылках в других проектах - перекомпиляция сборки зависимости вынуждает перекомпилировать и все зависимые сборки. В вашем случае у VM есть сильная ссылка на эту сборку из-за типов Person и Product. А у проекта View есть сильная ссылка на сборку VM. Поэтому такое простое изменение имени БД приведёт к перекомпиляции сборок всех слоёв. А это именно то с чем призваны бороться паттерны MV*.
0
 Аватар для Andrey-MSK
3386 / 2272 / 388
Регистрация: 14.08.2018
Сообщений: 7,690
Записей в блоге: 4
27.02.2024, 10:19
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Например, вы захотели просто изменить название БД:
Цитата Сообщение от Элд Хасп Посмотреть сообщение
То, что это приведёт к перекомпиляции сборки РЕАЛИЗАЦИИ - это нормально.
Это не нормально - все строки подключения хранят в конфигурационных файлах. Это и позволяет избежать пересборки именно по этой причине.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16164 / 11284 / 2891
Регистрация: 21.04.2018
Сообщений: 33,169
Записей в блоге: 2
27.02.2024, 10:19
xellan24rus, представьте себя себе руководителем мирового мегапроекта.
Над каждым вашим проектом работает своя отдельная команда. Каждая команда имеет свою территориальную локацию: США, Россия, Индия и т.д.
Вы раздали командам контракты (интерфейсы или базовые классы), которые они должны реализовать.
И после этого нужно обеспечить независимость работы команд.
Не должно быть такого, что мелкие изменения внесённые одной командой приводят к необходимости вносить изменение (перекомпилировать) их сборки (проекты).
0
 Аватар для xellan24rus
364 / 296 / 55
Регистрация: 08.04.2020
Сообщений: 1,175
27.02.2024, 10:21  [ТС]
Цитата Сообщение от wizard41 Посмотреть сообщение
хоть вопрос адресован Элд Хасп'
Тем не менее ответ был общим для вас.
Цитата Сообщение от wizard41 Посмотреть сообщение
О типе ProductData должен сообщить интерфейс, а выбрать коллекцию ProductData должна модель и передать ее VM.
сейчас модель данных такая, она наследует свой интерфейс > public class ProductData: ViewModelBase, IProduct
Если я сделаю public interface ProductData: ViewModelBase, IProduct тогда ViewModelBase не будет являться интерфейсом и придется наследовать в Vm и делать повторную реализацию. Поэтому не совсем понимаю зачем дублировать код интерфейса, ведь для Vm модель данных уже реализована.

Цитата Сообщение от wizard41 Посмотреть сообщение
Грубо говоря: ты скрыл от всех реализацию сбора данных, и никто не должен знать как она работает. Может быть она шифрованная и в объекты их преобразует твой супер-алгоритм, который ты никому не хочешь показывать.
Я прихожу со своим окном (VM) и говорю - дай-ка мне свои данные из БД... И тебе придется раскрыть мне добрую половину своих моделей/типов, чтобы мое окно поняло то, что туда летит.
Я об этом писал выше что можно создать создать класс ProductRepository в котором будет минимум логики, но в этой модели будет заполнение данных. И так как Commnd поддерживает T классы, то в ProductRepository можно создать единственную ссылку на DataBase чтобы была возможность работать с DbSet.

Цитата Сообщение от wizard41 Посмотреть сообщение
Я, однажды, уже прошел в некоторой степени "муки ада" понимания mvvm шаблона, впрочем, как и Элд Хасп, поэтому, нам, вероятно
Так всегда, я это понимаю.
Цитата Сообщение от wizard41 Посмотреть сообщение
не прибегая к помощи фреймворков.
Это не столь важно, ведь если источник будет Json, то базовая реализация для данных, всё равно останется. Изменится только работа с этими данными, но не ссылки и т.п.

Элд Хасп, пока занят был обдумывал всё. Про сильные зависимости, к примеру есть ConsoleApp.
В нем есть некий код
C#
1
Command<User> user = new Command<User>();
я использую user, то есть напрямую ссылаюсь на DataBase, чтобы разделить это зависимость, я должен создать класс UserRepository у него нет смысла реализовывать IUser, ведь свойства этого интерфейса вообще не нужны для ConsoleApp, нужна только работа с бд, за работу с бд отвечает Command класс, тогда в UserRepository я объявляю
C#
1
Command<User> User = new Command<User>();
и уже из ConsoleApp использую реализацию UserRepository. И этот UserRepository будет един для всех проектов и тогда сильная зависимость для DataBase исчезнет. И по аналогии нужно сделать для остальных классов, тоже самое. Я правильно понял?
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16164 / 11284 / 2891
Регистрация: 21.04.2018
Сообщений: 33,169
Записей в блоге: 2
27.02.2024, 10:22
Цитата Сообщение от Andrey-MSK Посмотреть сообщение
Это не нормально - все строки подключения хранят в конфигурационных файлах. Это и позволяет избежать пересборки именно по этой причине.
Да.
Но в данном случае, это удобный пример мелкого изменения, которое не должно приводить к изменению других сборок.
0
 Аватар для xellan24rus
364 / 296 / 55
Регистрация: 08.04.2020
Сообщений: 1,175
27.02.2024, 10:23  [ТС]
Цитата Сообщение от Andrey-MSK Посмотреть сообщение
все строки подключения хранят в конфигурационных файлах. Это и позволяет избежать пересборки именно по этой причине.
Ну тут реализация проще, поэтому этот вопрос отпадает, но замечание хорошее.
0
 Аватар для Andrey-MSK
3386 / 2272 / 388
Регистрация: 14.08.2018
Сообщений: 7,690
Записей в блоге: 4
27.02.2024, 10:24
Цитата Сообщение от Элд Хасп Посмотреть сообщение
это удобный пример мелкого изменения
Это не мелкое изменение. Это нарушение соглашений, которое ведёт за собой кучу потраченного зря времени...
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16164 / 11284 / 2891
Регистрация: 21.04.2018
Сообщений: 33,169
Записей в блоге: 2
27.02.2024, 10:28
Цитата Сообщение от xellan24rus Посмотреть сообщение
Про сильные зависимости, к примеру есть ConsoleApp.
Это проект ПРИЛОЖЕНИЯ, а не View.
Приложение - это место сборки всех его частей. Поэтому там могут быть сильные ссылки на любые сборки.
Пример: получен экземпляр DataSet по сильной ссылке, потом он внедрён в экземпляр Command (Модели) по слабой ссылке, который дальше внедрён в экземпляр VM тоже по слабой ссылке, а тот внедрён по слабой ссылке в View.
То есть App имеет сильный ссылки на все слои, но создание зависимостей между слоями происходит по слабым ссылкам.
0
 Аватар для xellan24rus
364 / 296 / 55
Регистрация: 08.04.2020
Сообщений: 1,175
27.02.2024, 10:29  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
И после этого нужно обеспечить независимость работы команд.
Нужно для каждого интерфейса реализовать репозиторий? Я чуть выше задавался этим вопросом.
Я так понимаю это уберет лишние зависимости. Но тем не менее для ProductData так как он реализует IProduct и используется в ObservableCollection<ProductData> ProductDataList, то есть свойство для Vm. Вот тут я не понял, зачем интерфейс для Vm то нужен.... Если под каждый чих делать интерфейс, то придется слишком сильно скакать.
Ведь если делать репозиторий для Product, то команды базовые будут реализованы и в одну строчку использованы в Vm для нужной команды.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16164 / 11284 / 2891
Регистрация: 21.04.2018
Сообщений: 33,169
Записей в блоге: 2
27.02.2024, 10:33
Цитата Сообщение от Andrey-MSK Посмотреть сообщение
Это нарушение соглашений,
Ну.... и да, и нет.
Если там только строка подключения - это одно.
А если изменения типа Хранилища, его архитектуры, то изменение строки подключения в настройках приложения не всегда хватит.
В данном случае - это детали реализации Репозитория, которые по большому счёту к рассматриваемой ьтеме не имеют отношения. Важно только чтобы детали реализации Репозитория не влияли на другие слои.
0
 Аватар для xellan24rus
364 / 296 / 55
Регистрация: 08.04.2020
Сообщений: 1,175
27.02.2024, 10:34  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
То есть App имеет сильный ссылки на все слои, но создание зависимостей между слоями происходит по слабым ссылкам.
С ссылками ясно всё, а про реализацию UserRepository и т.п что скажете? Для каждой модели данных допустим есть своя реализация репозитория для работы с ними, то есть эта ссылка будет доступна для всех решений, но изменения едины для всех проектов если изменить UserRepository и т.п
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16164 / 11284 / 2891
Регистрация: 21.04.2018
Сообщений: 33,169
Записей в блоге: 2
27.02.2024, 10:40
Цитата Сообщение от xellan24rus Посмотреть сообщение
Если под каждый чих делать интерфейс, то придется слишком сильно скакать.
Должна быть точка развязки сильных связей.
Это может быть интерфейс, может быть базовый (абстрактный класс). Но он должен быть в отдельной сборке от его реализации. Иначе не получится убрать сильные связи между слоями.
Как будет время (на выходных скорее всего) - я покажу в своей ветке, как это нужно сделать.
Для этого не требуется много времени - время требуется для вникания в проект, так как просто забываю что и как там. В том числе введение контрактов, вместо сильных связей, очень сильно экономит время для сторонних разработчиков необходимое для вникание в решение.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
27.02.2024, 10:40

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

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

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

Kivy для создания простого приложения
Всем привет ,я делаю простую программу на python, но никак не могу решить 2 проблемы. 1) Никак не меняется фон ModalView, хотя уже все...

Пример переключения между окнами WPF MVVM
Здравствуйте. Изучаю как можно переходить между окнами в wpf в рамках MVVM. Изучаю данный пример: ...


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

Или воспользуйтесь поиском по форуму:
100
Ответ Создать тему
Новые блоги и статьи
Кредитный калькулятор
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