Форум программистов, компьютерный форум, киберфорум
C#: WPF, UWP и Silverlight
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.71/7: Рейтинг темы: голосов - 7, средняя оценка - 4.71
 Аватар для firnen_dragon
25 / 25 / 4
Регистрация: 21.01.2019
Сообщений: 407

События в XAML и конструкторе окна

20.06.2023, 15:09. Показов 1600. Ответов 25
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Вопрос общего характера:
допустим у меня есть элемент в XML например вот такой:
XML
1
2
3
        <Viewbox Grid.Column="1" Margin="98,265,-98,57">
            <Calendar x:Name="Calendar" SelectedDate="{Binding SelectedDateTime}" />
        </Viewbox>
Если я подписываюсь на событие SelectedDatesChanged в XML то событие срабатывает до инициализации конструктора окна ну соответственно и до события Loaded тоже. В связи с этим ловлю исключения связанные с тем что vm еще не инициализирована (инициализирую я ее обычно в конструкторе окна). Когда возникает такая проблема я просто подписываюсь на нужное событие в конструкторе окна, ну и получается, что у меня часть событий подписана в XML, а часть в коде окна, не думаю, что это хорошо, может как-то можно подписываться на все события в xml и не ловить подобные исключения?

Не по теме:


Не бейте, если это что-то очевидное, для меня это не так уж понятно.



Добавлено через 17 минут
Цитата Сообщение от firnen_dragon Посмотреть сообщение
событие срабатывает до инициализации конструктора окна
Точнее, наверное, не до конструктора, а до присвоения DataContext в конструкторе.

Добавлено через 2 часа 49 минут
не знаю на сколько это корректно, но в обработчике можно вот так проверять загружен ли элемент:
C#
1
2
3
4
if (Calendar.IsLoaded)
{
     //тут расписывать логику
}
0
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
20.06.2023, 15:09
Ответы с готовыми решениями:

Подсветка слова в XAML при выборе элемента в конструкторе формы
Как поменять цвет? Когда выделяешь элемент в конструкторе формы он подсвечивается в XAML виде формы слишком тускло - светлым серым и в...

При задании значения в своём свойстве в xaml оно всегда null в конструкторе контрола
Добавляю своё свойство в контрол, чтобы его можно было задавать через xaml public class CheckBoxDataGridControl :...

События не компилируемого xaml
Есть не компилируемый xaml, который подключается в программе. В программе создан метод: private void label1_MouseUp(object sender,...

25
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16152 / 11273 / 2890
Регистрация: 21.04.2018
Сообщений: 33,147
Записей в блоге: 2
23.06.2023, 12:36
Студворк — интернет-сервис помощи студентам
firnen_dragon, если речь не об изучении, обучении, а о практике, о реальной работе, то советую попробовать Fody - очень удобная штука.

Добавлено через 4 минуты
MS рекомендует Windows Community Toolkit. Тоже хороший пакет. Но Fody мне нравится больше.
Для построения мощной логики в VM советую освоить Reactive. Очень мощный фрамеворк. НО требует достаточных времени и усилий по изучению. Там даже свой пласт теории "Реактивное программирование".
1
 Аватар для firnen_dragon
25 / 25 / 4
Регистрация: 21.01.2019
Сообщений: 407
23.06.2023, 13:00  [ТС]
Andrey-MSK, Честно говоря ничего не понял, DI - это DependencyInjection? Я вот читаю про тему связывания слоев тут еще речь о локаторах идет через них связывать слои тоже можно ведь?

Добавлено через 16 минут
Элд Хасп, Да, речь по большей части о работе, но и понимать, что происходит тоже не помешало бы, спасибо, попробую Fody.
0
 Аватар для Andrey-MSK
3368 / 2254 / 388
Регистрация: 14.08.2018
Сообщений: 7,631
Записей в блоге: 4
23.06.2023, 13:04
Цитата Сообщение от firnen_dragon Посмотреть сообщение
DI - это DependencyInjection?
Оно
Цитата Сообщение от firnen_dragon Посмотреть сообщение
тут еще речь о локаторах идет
Ну я и показал пример локатора, но тут он по другому работает.
Мой пример из сборки Microsoft.Extensions.DependencyInjection
Тут довольно всё путано, и с наскока не понять
Вот пример моего App.xaml.cs. Написал комментарии как пользоваться...
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
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Threading;
using System.Windows;
using System.Windows.Markup;
 
using DALibrary;
using DALibrary.Interfaces;
 
using DBClient.Services;
using DBClient.Services.Interfaces;
using DBClient.Views.Dialogs;
using DBClient.Views.Windows;
 
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
 
using Services;
using Services.Interfaces;
using Services.Interfaces.DialogsVM;
using Services.Interfaces.WindowsVM;
 
using VModels.DialogsVM;
using VModels.WindowsVM;
 
namespace DBClient
{
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    public partial class App : Application
    {
        public IServiceProvider Services { get; }
        
        // Конфигурация приложения
        public IConfiguration Configuration { get; }
 
        // Класс приложения
        public new static App Current => (App)Application.Current;
 
        public App()
        {
            // Данная опция позволяет использовать тип обновления привязки UpdateSourceTrigger=PropertyChanged
            // для TextBox при вводе дробных значений.
            FrameworkCompatibilityPreferences.KeepTextBoxDisplaySynchronizedWithTextProperty = false;
 
            // Получаем конфигурацию
            Configuration = GetConfiguration();
            // Получаем список сервисов приложения
            Services = ConfigureServices();
 
            InitializeComponent();
        }
 
        // Настраиваем файл конфигурации приложения
        private static IConfiguration GetConfiguration()
        {
            var builder = new ConfigurationBuilder()
                .SetBasePath(AppDomain.CurrentDomain.BaseDirectory)
                .AddJsonFile("appsettings.json");
 
            return builder.Build();
        }
 
        private static IServiceProvider ConfigureServices()
        {
            var services = new ServiceCollection();
 
            // Создание коллекции сервисов
            // AddSingleton - запустить единичный экземпляр сервиса
            // AddTransient - запустить сервис по вызову
            // Сервисы все самописные, так что у вас их не будет, это просто пример
            services
                .AddSingleton(Current.Configuration)
                .AddSingleton<IMainDA, MainDA>()
                .AddSingleton<IViewModelsService, ViewModelsService>()
                .AddSingleton<IWindowService, WindowService>()
                .AddSingleton<IBackgroundTaskQueue, BackgroundTaskQueue>()
                .AddSingleton<IViewModelFactory, ViewModelFactory>()
                .AddTransient<IMainWindowVM, MainWindowVM>()
                .AddTransient<ICPSAddSpecificationDetailDialogVM, CPSAddSpecificationDetailDialogVM>()
                .AddTransient<ICPSContractEditDialogVM, CPSContractEditDialogVM>()
                .AddTransient<ICPSContractSelectDialogVM, CPSContractSelectDialogVM>()
                .AddTransient<ICPSDetailsPreviewDialogVM, CPSDetailsPreviewDialogVM>()
                .AddTransient<ICPSHeadersPreviewDialogVM, CPSHeadersPreviewDialogVM>()
                .AddTransient<IDrawAddDialogVM, DrawAddDialogVM>()
                .AddTransient<IDrawEditDialogVM, DrawEditDialogVM>();
 
            return services.BuildServiceProvider();
        }
 
        protected override void OnStartup(StartupEventArgs e)
        {
            IViewModelsService _viewModelsService
                = Current.Services.GetService<IViewModelsService>();
            IBackgroundTaskQueue _taskQueue
                = Current.Services.GetService<IBackgroundTaskQueue>();
 
            base.OnStartup(e);
 
            Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo("RU-ru");
            Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("RU-ru");
            FrameworkElement.LanguageProperty.OverrideMetadata(typeof(FrameworkElement),
                  new FrameworkPropertyMetadata(XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.IetfLanguageTag)));
 
            // Здесь самописный сервис связывает VM с нужным окном
            _viewModelsService
                .Register<MainWindowVM, MainWindow>()
                .Register<CPSAddSpecificationDetailDialogVM, CPSAddSpecificationDetailDialog>()
                .Register<CPSContractEditDialogVM, CPSContractEditDialog>()
                .Register<CPSContractSelectDialogVM, CPSContractSelectDialog>()
                .Register<CPSDetailsPreviewDialogVM, CPSDetailsPreviewDialog>()
                .Register<CPSHeadersPreviewDialogVM, CPSHeadersPreviewDialog>()
                .Register<DrawAddDialogVM, DrawAddDialog>()
                .Register<DrawEditDialogVM, DrawEditDialog>();
 
            // Запуск сервиса очереди асиннхронных методов
            _taskQueue.Start();
 
            // Настройка главного окна приложения
            // Из App.xaml убрать строчку StartupUri, так окно формируем тут
            MainWindow = new MainWindow { DataContext = Current.Services.GetService<IMainWindowVM>() };
            MainWindow.Show();
        }
    }
}
2
 Аватар для firnen_dragon
25 / 25 / 4
Регистрация: 21.01.2019
Сообщений: 407
23.06.2023, 13:07  [ТС]
Andrey-MSK, Спасибо, буду разбираться
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16152 / 11273 / 2890
Регистрация: 21.04.2018
Сообщений: 33,147
Записей в блоге: 2
23.06.2023, 13:23
Цитата Сообщение от firnen_dragon Посмотреть сообщение
Я вот читаю про тему связывания слоев тут еще речь о локаторах идет через них связывать слои тоже можно ведь?
На уровне WPF View-App часто под локаторами могут подразумевать иное.
Некий класс экземпляр которого объявляется в ресурсах App и из свойств которого можно получать экземпляры VM и других объектов.
Через него удобно связывать условно XAML и CB.
Самый известный пример такого локатора в первом (исторически) MVVM фрамеворке - MVVM Light. При установке его NuGet'a такой локатор автоматически добавляется в App.

Ещё можете здесь посмотреть Передача данных между Окнами, между VM, Шина Сообщений, Локатор [WPF, Элд Хасп]
1
 Аватар для Andrey-MSK
3368 / 2254 / 388
Регистрация: 14.08.2018
Сообщений: 7,631
Записей в блоге: 4
23.06.2023, 14:02
firnen_dragon, Забыл ещё добавить, вот сервис, который получает VM по её интерфейсу
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
using System;
 
using Microsoft.Extensions.DependencyInjection;
 
using Services.Interfaces;
 
namespace DBClient.Services
{
    public class ViewModelFactory : IViewModelFactory
    {
        private readonly IServiceProvider _serviceProvider;
 
        public ViewModelFactory(IServiceProvider serviceProvider)
        {
            _serviceProvider = serviceProvider;
        }
 
        public T CreateViewModel<T>() where T : IBaseViewModel
            => _serviceProvider.GetService<T>();
    }
}
И еще сервис для связи 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
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
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
 
using DBClient.Services.Interfaces;
 
using Services.Interfaces;
 
namespace DBClient.Services
{
    public class ViewModelsService : IViewModelsService
    {
        private readonly Dictionary<Type, Func<ContentControl>> _dict = new Dictionary<Type, Func<ContentControl>>();
 
        public IViewModelsService Register<TViewModelType, TViewType>()
            where TViewType : ContentControl, new()
            where TViewModelType : IBaseViewModel
        {
            _dict[typeof(TViewModelType)] = () => new TViewType();
 
            return this;
        }
 
        public Window GetWindow(IBaseViewModel viewModel)
        {
            var result = GetControl(viewModel);
 
            if (result is not Window window)
                throw new Exception($"{result.GetType()} is not window");
 
            return window;
        }
 
        public ContentControl GetControl(IBaseViewModel viewModel)
        {
            var parentTypes = GetParentTypes(viewModel.GetType());
 
            foreach (var parentType in parentTypes)
            {
                if (_dict.TryGetValue(parentType, out var res))
                    return res();
            }
 
            throw new Exception($"ViewModel {viewModel.GetType().Name} is not registered");
        }
 
        private static IEnumerable<Type> GetParentTypes(Type type)
        {
            // is there any base type?
            if (type == null)
                yield break;
 
            yield return type;
 
            // return all implemented or inherited interfaces
            foreach (var i in type.GetInterfaces())
                yield return i;
 
            // return all inherited types
            var currentBaseType = type.BaseType;
 
            while (currentBaseType != null)
            {
                yield return currentBaseType;
                currentBaseType = currentBaseType.BaseType;
            }
        }
    }
}
Остальное придумаете под ваши нужды

Добавлено через 2 минуты
firnen_dragon, И интерфейсы для них
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
using System.Windows;
using System.Windows.Controls;
 
using Services.Interfaces;
 
namespace DBClient.Services.Interfaces
{
    public interface IViewModelsService
    {
        Window GetWindow(IBaseViewModel viewModel);
        ContentControl GetControl(IBaseViewModel viewModel);
        IViewModelsService Register<TViewModelType, TViewType>()
            where TViewType : ContentControl, new()
            where TViewModelType : IBaseViewModel;
    }
}
C#
1
2
3
4
5
6
7
namespace Services.Interfaces
{
    public interface IViewModelFactory
    {
        T CreateViewModel<T>() where T : IBaseViewModel;
    }
}
Добавлено через 3 минуты
firnen_dragon, Вот в этом месте и производится внедрение зависимости (DI) при вызове AddSingleton (AddTransient)
C#
1
2
3
4
public ViewModelFactory(IServiceProvider serviceProvider)
{
    _serviceProvider = serviceProvider;
}
С конструкторами VM точно также.

Добавлено через 34 минуты
firnen_dragon, Вот так можно этим добром пользоваться в VM - https://www.cyberforum.ru/blog... g8023.html
2
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
23.06.2023, 14:02
Помогаю со студенческими работами здесь

События срабатывают в конструкторе формы
Есть событие по нажатию кнопки на форме и событие, возникающее при получении фокуса текстовым полем. Но они срабатывают раньше, когда форма...

События контролов xaml и как избежать рекурсии
Здравствуйте. Возникла такая проблема. У меня есть TextBox и переменная float. При изменении текста в TextBox должно изменяться значение...

Необязательные аргуметы в конструкторе окна
Столкнулся с тем, что в WPF программах, в отличии от WF даже необязательные параметры выдают ошибку. Пример: public partial class...

WPF(XAML) анимация сокрытие окна
Доброго дня. Рисую окно, по нажатию на кнопку часть окна должна скрываться, оставляя нажатую кнопку на месте, а при повторном нажатии...

НЕ открываются окна функций для КНОПКИ в конструкторе
При попытке в форму встроить кнопку, например для открытия другой формы, перестало открываться окно подсказки для выбора функций...


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

Или воспользуйтесь поиском по форуму:
26
Ответ Создать тему
Новые блоги и статьи
19. здоровье, усталость и психотип работника влияют на производительность предприятия, и наоборот, производительность на здоровье, усталось и психотип
anaschu 28.05.2026
Дискретно-событийная модель рабочего коллектива на AnyLogic: здоровье, выгорание, психотипы и микростимуляция Привет, коллеги. Хочу поделиться итогами нескольких недель работы над симуляционной. . .
"Прокси" для последовательного порта
Eddy_Em 28.05.2026
Эту штуку написал я достаточно давно. Но сейчас вот понадобилось настроить датчик грозы, но при этом не отключать его от "метеодемона". Соответственно, надо запустить этот "прокси": метеодемон будет. . .
Рефакторинг программы уравнивания.
Massaraksh7 26.05.2026
Пример по предыдущей записи в блоге. Но, надо заметить, что, во-первых, там оптимизация не только математики, но и работы с базой данных, и с графами, а во-вторых, это ещё не всё.
Использование TThread в Lazarus для математических вычислений.
Massaraksh7 25.05.2026
Производя рефакторинг своих программ на предмет ускорения их работы, обратил внимание на такой аспект, как сокращение времени матвычислений. Дело в том, что приходится работать с большими матрицами. . .
Модель здравосохранения 18. Чем здоровее работник, тем быстрее выгорает
anaschu 24.05.2026
Имитационная модель корпоративного здравоохранения: что показывает математика Сегодня в модели рабочего коллектива на AnyLogic появились три новые механики — выгорание через накопленную усталость,. . .
Модель здравосохранения 17. Планы на выгорание
anaschu 23.05.2026
Вот конкретная схема реализации: В классе Работник добавить: накопленнаяУсталость — растёт каждый час работы, снижается в перерывы и болезни коэффициентПрезентеизма — снижает продуктивность. . .
Изменение цветов в палитре gif файла aka фавикона
russiannick 23.05.2026
Изменение цветов в палитре gif файла, юзаемого как фавиконка в составе html-файла, помещенная в base64, средствами нативного Java Script, навеянное сном в майский день. Для работы необходим браузер,. . .
Модель здравосохранения 16. Слишком хорошие и здоровые сотрудники уходят, недовольные зарплатой
anaschu 23.05.2026
Отладка увольнений и настройка производительности Сегодня во второй половине дня разобрались с механикой увольнений и настроили коэффициент сложности заданий. Вот что было сделано. . . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru