Форум программистов, компьютерный форум, киберфорум
C#: WPF, UWP и Silverlight
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.56/16: Рейтинг темы: голосов - 16, средняя оценка - 4.56
1341 / 920 / 265
Регистрация: 08.08.2014
Сообщений: 2,775

DI на этапе создания контрола из XAML

29.10.2020, 00:47. Показов 3496. Ответов 45
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Есть простейший ContentControl, расположенный в какой-то вспомогательной общей библиотеке:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
    public sealed class ViewModelControl : ContentControl
    {
        public IViewService ViewService { get; set; }
 
        public static readonly DependencyProperty ViewModelProperty = DependencyProperty.Register(
            nameof(ViewModel),
            typeof(object),
            typeof(ViewModelControl),
            new PropertyMetadata(default(object), OnViewModelChanged));
 
        public object ViewModel
        {
            get => GetValue(ViewModelProperty);
            set => SetValue(ViewModelProperty, value);
        }
 
        private static void OnViewModelChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
        {
            this.Content = ViewService.LoadUserControl((o as ViewModelControl).ViewModel);
        }
    }
И он используется в каком-то XAML:
XML
1
<vm:ViewModelControl ViewModel="{Binding Path=NestedViewModel}" />
И в каком-то приложении на базе этого XAML создаётся 'UserControl', который где-то размещается:
C#
1
window.Content = Application.LoadComponent(viewXamlInfo.Uri);
И в рамках этого 'LoadComponent', помимо прочего, так же создаётся один (или боллее) экземпляр 'ViewModelControl' (т.к. он есть в XAML).

И далее этому экземпляру 'ViewModelControl' в некий момент в рантайме приходит событие 'OnViewModelChanged' и ему нужно через 'ViewService', для текущего типа экземлпяра 'ViewModel':
1. Найти XAML, который сопоставлен данной ViewModel (логика сопоставления известна только уровню приложения, т.е. там, где происходит 'Application.LoadComponent').
2. Cоздать UserControl на базе этого XAML.

Вопрос: как наименее затратно по коду/времени и не нарушая иерархию зависимостей выдать всем экземплярам 'ViewModelControl' (созданным в процессе создания контрола на базе XAML) экземпляр сервиса 'IViewService' (реализованого на уровне приложения, которое всё это использует)?

Пока что единственный вариант, что удалось придумать - после выполнения 'Application.LoadComponent', пройтись при при помощи 'LogicalTreeHelper' по всему дереву элементов, найти все экземпляры 'ViewModelControl' и выдать им реализацию сервиса резолва/создания View через внешнее свойство типа IViewService.

Однако, это не самый быстрый вариант, особенно, для XAML с большим количеством элементов.
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
29.10.2020, 00:47
Ответы с готовыми решениями:

Обращение к элементу UI своего контрола-наследника из xaml другого класса
Создаю свой контрол - наследник от Grid в коде .cs В своём контроле добавляется TextBox Вопрос: как сделать так, чтобы обращение к...

Создание собственного контрола. Наследник textbox не отображает xaml код
Делаю свой контрол, который наследуется от textBox. Но контрол в дизайнере проекта не отображается, где я его собственно стряпаю. Вопрос:...

Зависает на этапе создания окна!
Зависает на этапе создания окна. До списков даже не доходит... // laba11.cpp : Defines the entry point for the application. // ...

45
1341 / 920 / 265
Регистрация: 08.08.2014
Сообщений: 2,775
04.11.2020, 01:55  [ТС]
Студворк — интернет-сервис помощи студентам
Попробовал с нуля прописать оба подхода для существующего десктопного приложения (со сложной UI-логикой).

В итоге да, получается, что подход View-first наиболее применим, т.к., в отличие от VM-first, даёт полную свободу реализации UI под конкретную платформу без наращивания бесконечных абстракций по управлению View-слоем со стороны VM. Ну т.е. если вся логика управления UI находится во VM (а View содержит только разметку и биндинги), то даже элементарная операция позиционирования окна вынуждает выдавать VM какой-нибудь интерфейс IView, который в конечном итоге начинает дублировать вообще все свойства/методы UI-контролов.

Правда, при подходе View-first я пока совершенно не уловил, зачем там вообще какие-либо фрейморки нужны. Там ведь для VM-слоя нужен самый минимум логики и вспомогательного кода. Разве что для упрощения создания/связывания V и VM. Более того, если посмотреть на существующее приложение, то там больше половины кликов в UI-кнопки/элементы к в VM прямого отношения не имеют, т.е. их нельзя просто взять и забиндить на ICommand, т.к., помимо собственно обращений к модели за логикой предметной области (через VM), они так же реализуют сложную пре/пост UI-логику взаимодействия с пользователем. Например, пользователь нажал кнопку, далее, в зависимости от состояния исходных/введённых данных, нужно показать пользователю какое-то предупреждение в мессаджбоксе (или даже полноценный самописный диалог с подробными данными) и, в зависимости от выбора пользователя, либо скипнуть выполнение, либо вызвать один из нескольких методов ViewModel, а после получения результата, проанализировать его и, вероятно, показать ещё какое-нибудь окно со статистикой выполнения (и это всё в рамках клика).
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,176
Записей в блоге: 2
04.11.2020, 10:31
Цитата Сообщение от kotelok Посмотреть сообщение
Правда, при подходе View-first я пока совершенно не уловил, зачем там вообще какие-либо фрейморки нужны. Там ведь для VM-слоя нужен самый минимум логики и вспомогательного кода.
А так оно и есть в действительно широко используемых фрамеворках.
Даже есть взять мощнейший ReactiveUI.

Добавлено через 4 минуты
Цитата Сообщение от kotelok Посмотреть сообщение
Более того, если посмотреть на существующее приложение, то там больше половины кликов в UI-кнопки/элементы к в VM прямого отношения не имеют, т.е. их нельзя просто взять и забиндить на ICommand, т.к., помимо собственно обращений к модели за логикой предметной области (через VM), они так же реализуют сложную пре/пост UI-логику взаимодействия с пользователем.
Поэтому существует множество различных навигаторов.
Многие из них работают через Контекст Данных.
И по этой причине их часто называют ViewModel, хотя, как я писал раньше, это неверно.
И эта неверная терминология приводит к путанице в понимании особенно для начинающих.

Добавлено через 9 минут
Цитата Сообщение от kotelok Посмотреть сообщение
Например, пользователь нажал кнопку, далее, в зависимости от состояния исходных/введённых данных, нужно показать пользователю какое-то предупреждение в мессаджбоксе (или даже полноценный самописный диалог с подробными данными) и, в зависимости от выбора пользователя, либо скипнуть выполнение, либо вызвать один из нескольких методов ViewModel, а после получения результата, проанализировать его и, вероятно, показать ещё какое-нибудь окно со статистикой выполнения (и это всё в рамках клика).
В этом сценарии важно понимать, что является реакцией View непосредственно на действия пользователя, а что опосредованно, как результат изменения состояния данных.

Для облегчения этого понимания, необходимо сначала строить Модель - по ней будет понятно, что, собственно, я вляется Данными и методами работы с ними.
А при построении View надо создавать интерфейсы VM и их временную реализацию для Контекста Данных Времени Разработки (CDDD).
Очень часто это удобно делать в виде базовой ViewModel (VMDD).
Поэтому во многих фрамефорках в VM встроена возможность определения Режима Разработки.
Но я предлагаю пойти даже дальше создавать базовую VM полностью реализующую "сторону View".
И реализованная View должна позволять совершить полную отладку GUI на этой базовой VMDD.
1
1341 / 920 / 265
Регистрация: 08.08.2014
Сообщений: 2,775
05.11.2020, 00:41  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
ReactiveUI
Какой-то странный фреймворк. Во всех примерах, в т.ч. на офф-сайте - минимум XAML, максимум CB. Даже биндинги все прописываются кодом в конструкторе. Весьма неудобно, т.к. сначала нужно через 'x:Name' сгенерировать поле для ссылки на контрол, запомнить его, а потом в CB задать для него биндинг. В итоге описание контрола размазывается и, смотря на контрол в XAML, совершенно не понятно куда и как он забинден. И в CB (в конструкторе) получается огромная простыня кода.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,176
Записей в блоге: 2
05.11.2020, 01:09
Цитата Сообщение от kotelok Посмотреть сообщение
Какой-то странный фреймворк.
Это фрамеворк нацелен на создание VM со сложной внутренней логикой.
Ок как бы учитывает, что VM будет использоваться с View, но каких-то специальных средств по работе с ней нет.
И он является реализацией "Реактивного программирования".
Для тех кто умеет им пользоваться позволяет реализовывать очень многое, и очень быстро.

Цитата Сообщение от kotelok Посмотреть сообщение
И в CB (в конструкторе) получается огромная простыня кода.
Не должно получаться.


kotelok, обсуждение становится каким-то через чур абстрактным, оторванным от реальности.
Дать какой-то совет применимый всегда и во всех случаях - я не могу.
Может не хватает знаний, может не хватает способностей объяснить, то что знаю и понимаю...

Надо как-то "приземлиться" из заоблачных тем.
0
1341 / 920 / 265
Регистрация: 08.08.2014
Сообщений: 2,775
05.11.2020, 09:17  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Не должно получаться.
Не должно. Однако, инициализация даже маленькой тестовой главной формы выглядит как в цитате ниже (если же это будет реальная форма с большим количеством элементов, то расползётся это всё на многие страницы). Понятно, что это снижение читаемости/сопровождаемости делается в угоду каким-то другим возможностям, но сходу такой подход выглядит странно.
Кликните здесь для просмотра всего текста
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
public MainView()
{
    InitializeComponent();
 
    LayoutViewModel = Locator.Current.GetService<ILayoutViewModel>();
 
    this.WhenActivated(
        d =>
            {
                d(this.WhenAnyValue(x => x.DockManager).BindTo(LayoutViewModel, vm => vm.DockingManager));
                d(ViewModel.SelectFolder.RegisterHandler(HandleFolderPrompt));
                d(this.BindCommand(ViewModel, vm => vm.NewRepository, view => view.NewMenuItem));
                d(this.BindCommand(ViewModel, vm => vm.SelectRepository, view => view.OpenMenuItem));
                d(
                    this.OneWayBind(
                        ViewModel,
                        vm => vm.RepositoryViewModels,
                        view => view.DockManager.DocumentsSource));
                d(
                    this.Bind(
                        ViewModel,
                        vm => vm.SelectedRepositoryViewModel,
                        view => view.DockManager.ActiveContent,
                        viewToVMConverterOverride: new DocumentTypeConverter()));
                d(
                    this.OneWayBind(
                        ViewModel,
                        vm => vm.VisibleSupportViewModels,
                        view => view.DockManager.AnchorablesSource));
                d(HandleLayout());
                d(this.WhenAnyValue(x => x.LayoutViewModel.ResetLayout).BindTo(this, view => view.ResetWindowLayout.Command));
            });
}

Цитата Сообщение от Элд Хасп Посмотреть сообщение
Надо как-то "приземлиться" из заоблачных тем
Пока не получается. Т.к. с одной стороны - не охота снова велосипедить (даже по-минимуму), с другой - готовые популярные фреймворки не слишком удобны даже на первый взгляд.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,176
Записей в блоге: 2
05.11.2020, 12:08
Цитата Сообщение от kotelok Посмотреть сообщение
с другой - готовые популярные фреймворки не слишком удобны даже на первый взгляд.
Я тоже не смог выбрать для постоянного пользования какой-то конкретно.
На мой непросвещённый взгляд (я всё таки любитель, а не профессионал), основная их цель упрощение кодирования.
А они что-то упрощают, но в целом не сказать, что делаю реализацию роще, понятнее, читабельней.

Единственное, что советую - это использование Fody.
Это даже не фрамеворк, а просто автоматическая имплантация INPC в автосвойства.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
05.11.2020, 12:08

Ошибки на этапе создания проекта
Доброго времени суток! Начал своё знакомство с Ruby on Rails пару дней назад, и уже столкнулся с рядом проблем, на которые в интернете...

MySQL виснет при установке, на этапе создания my.ini
Привет. Раньше устанавливал мускуль и все было четко. А сейчас уже 10 раз пробовал установить сервер mysql и постоянно идет зависание на...

На каком этапе создания сайта можно приступать к оптимизации
Здравствуйте друзья оптимизаторы. Кому не трудно посмотреть на сайт toursector.org.ua и указать на ошибки которые стоит исправить перед...

DBGrid: как отключить отображение информации на этапе создания?
Здравствуйте! Подскажите чайнику как в DBGrid delphi отключить отображение информации на этапе создания? В виртуальной машине пытаюсь...

Зависает на этапе создания окна. До списков даже не доходит
Зависает на этапе создания окна. До списков даже не доходит... // laba11.cpp : Defines the entry point for the application. // //...


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

Или воспользуйтесь поиском по форуму:
46
Ответ Создать тему
Новые блоги и статьи
Запустил конкурс "тем и промптов для текстовых квестов созданных почти чисто ИИ"
Adler 06.10.2026
Всем привет! За последние три-четыре дня я создал более 16 текстовых квестовых игр используя преимущественно по одному запросу к ИИ на игру. Мне так понравилось смотреть все ветки/ сцены во всех. . .
ИИ не может найти нужный язык в списке
Supersumestria 05.10.2026
Я ему даю вот такое изображение и прошу найти и подчеркнуть немецкий язык. Возвращает он вот это: https:/ / i. **********/ vqBWLe2. png Нужную строчку в 3й колонке просто выдумал. . Это. . .
Новая последняя моя музыка в SUNO
zorxor 05.10.2026
Здравствуйте, дорогие мои друзья! С большой радостью я хотел бы представить вам свою новую последнею музыку, которую сгенерировала мне по моей просьбе нейросеть SUNO. С уважением, zorxor. Это. . .
Программный домашний кинотеатр
russiannick 27.09.2026
Сподобился на программный домашний кинотеатр. В качестве ЯВУ по традиции выбрал js. В помощники взял Яндекс-Алису. Было создано три зала на разные интересы. исторические и ретро сериал Хичкок. . .
Беседа с ИИ о программистах, недопускающих к созданию и правке кода генеративные ИИ и причины этого
zorxor 21.09.2026
Раньше я радовался или получал некоторые эмоции, пусть небольшие, но всё же, от самого процесса написания кода, рекомпиляции и запуска, видя постепенное развитие программы и прочее. А теперь лень. . .
Мобильное приложение ColorStep
pavlinmavlin 17.09.2026
Реализовал приложение Красный, Зеленый, Синий в Unity3d + c#. Название изменил на ColorStep. Приложение прошло модерацию и теперь доступно для скачивания. Делал его сам, шаг за шагом — и вот,. . .
Запрет дублирования строк в табличной части
Maks 13.09.2026
Реализация из решения ниже выполнена на нетиповом справочнике "Нормы ТО" с табличной часть "Виды ТО", разработанного в КА2, со следующими реквизитами: - ВидТО (СправочникСсылка. ВидыТО); - ВидГСМ. . .
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр.
Jin X 06.09.2026
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр. Работая с форумом и нейросетями в браузере часто хочется что-то подкорректировать или добавить какого-то функционала. Ниже прикреплён. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru