Форум программистов, компьютерный форум, киберфорум
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. Показов 1460. Ответов 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
 Аватар для Элд Хасп
16115 / 11236 / 2887
Регистрация: 21.04.2018
Сообщений: 33,037
Записей в блоге: 2
21.06.2023, 16:34
Лучший ответ Сообщение было отмечено firnen_dragon как решение

Решение

Цитата Сообщение от firnen_dragon Посмотреть сообщение
В связи с этим ловлю исключения связанные с тем что vm еще не инициализирована
Ну, так не нужно из обработчиков View обращаться к VM.
Есть привязка SelectedDate="{Binding SelectedDateTime}". Вот и обрабатывайте в VM изменение его свойства.
1
 Аватар для firnen_dragon
25 / 25 / 4
Регистрация: 21.01.2019
Сообщений: 407
21.06.2023, 17:55  [ТС]
Элд Хасп, Спасибо
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16115 / 11236 / 2887
Регистрация: 21.04.2018
Сообщений: 33,037
Записей в блоге: 2
21.06.2023, 18:15
Цитата Сообщение от firnen_dragon Посмотреть сообщение
не знаю на сколько это корректно, но в обработчике можно вот так проверять загружен ли элемент:
Даже, если возникла настоятельная необходимость обратиться в CB к VM, то лучше проверять его наличие:
C#
1
2
3
4
5
6
7
private void SomeHandler(.....)
{
    if(DataContext is SomeViewModel vm)
    {
        // Здесь работаем с переменной vm
    }
}
В чём проблема обращения к VM в обработчиках.
Возьмём ваш пример переделанный под обработчик:
XML
1
2
3
<Calendar x:Name="Calendar"
          SelectedDateChanged="OnSelectedDatesChanged"
          SelectedDate="23.02.2020"/>
C#
1
2
3
4
5
6
7
private void OnSelectedDatesChanged(.....)
{
    if(DataVontext is SomeViewModel vm)
    {
        vm.SelectedDateTime = Calendar.SelectedDate;
    }
}
Вроде всё работает, но!!!
Так как событие сработало до присвоения DataContext, то в свойство vm.SelectedDateTime не будет записана дата "23.02.2020". А пользователь в GUI будет действовать исходя из предположения, что дата уже задана.
1
 Аватар для firnen_dragon
25 / 25 / 4
Регистрация: 21.01.2019
Сообщений: 407
22.06.2023, 10:49  [ТС]
Элд Хасп, Спасибо, я понял, что из события что-то делать - плохо, но у меня вся "логика" приложений построена на том, что я подписываюсь на события и из них обращаюсь к vm, и по этому я не пойму как по другому-то нужно делать?(это все винформы виноваты).
Вот абстрактный пример:
у меня есть TextBox, ComboBox и Button
мне нужно по клику кнопки обновить коллекцию в combobox с учетом того, что написано в TextBox(это имитация запроса с базы данных). Как делал бы я:
Я б создал статический класс в котором будет происходить создание новой коллекции(или любая другая обработка коллекции) в моем понимании это и есть модель:
Кликните здесь для просмотра всего текста

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
    public static class StaticClass
    {
        static public ObservableCollection<Item> Processing(string text)
        {
            var Collection = new ObservableCollection<Item>();
            Collection.Add(new Item() { Name = text, Category = "A", Value = 5 });
            Collection.Add(new Item() { Name = "Item4", Category = "A", Value = 7 });
            Collection.Add(new Item() { Name = "Item3", Category = "A", Value = 5 });
            Collection.Add(new Item() { Name = "Item2", Category = "B", Value = 20 });
            Collection.Add(new Item() { Name = "Item1", Category = "B", Value = 30 });
            return Collection;
        }
    }

В XML подписался бы на событие клика по конопке(В моем понимании то что написано в XML это View ):
Кликните здесь для просмотра всего текста

XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
    <Window.DataContext>
        <local:MainViewModel/>
    </Window.DataContext>
    <Grid>
        <TextBox x:Name="textBox" TextWrapping="Wrap" Text="{Binding Text}" Margin="74,25,189,261"/>
        <ComboBox ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem}"  x:Name="comboBox" Margin="74,63,189,223">
            <ComboBox.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Name}"/>
                </DataTemplate>
            </ComboBox.ItemTemplate>
        </ComboBox>
        <Button x:Name="button" Click="button_Click" Content="Button" Margin="74,109,189,153"/>
    </Grid>

В Vm использовал бы свой пресловутый Display()
Кликните здесь для просмотра всего текста

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
    public class MainViewModel 
    {
 
        public ObservableCollection<Item> Items { get; }
        public Item SelectedItem { get; set; }
        public string Text { get; set; }
 
        public MainViewModel()
        {
            Items = new ObservableCollection<Item>();
            Items.Add(new Item() { Name = "Item1", Category = "A" , Value = 5});
            Items.Add(new Item() { Name = "Item2", Category = "A" , Value = 7});
            Items.Add(new Item() { Name = "Item3", Category = "A" , Value = 5});
            Items.Add(new Item() { Name = "Item4", Category = "B" , Value = 20});
            Items.Add(new Item() { Name = "Item5", Category = "B" , Value = 30});
        }
        public void Display(ObservableCollection<Item> list)
        {
            Application.Current.Dispatcher.BeginInvoke(new Action(() =>
            {
                Items.Clear();
                for (int i = 0; i < list.Count; i++)
                {
                    Items.Add(list[i]);
                }
            }));
        }
 
    }

Ну и в обработчике клика вызвал бы этот Display() и Processing():
Кликните здесь для просмотра всего текста

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
    public partial class MainWindow : Window
    {
        MainViewModel ViewModel;
        public MainWindow()
        {
            InitializeComponent();
            ViewModel = (MainViewModel)DataContext;
        }
 
        private void button_Click(object sender, RoutedEventArgs e)
        {
            ViewModel.Display(StaticClass.Processing(ViewModel.Text));
        }
    }

Вот вопрос как достичь того же результат, но только по mvvm? Потому что как я понимаю у меня не mvvm.
0
 Аватар для Andrey-MSK
3312 / 2199 / 387
Регистрация: 14.08.2018
Сообщений: 7,400
Записей в блоге: 4
22.06.2023, 11:21
Цитата Сообщение от firnen_dragon Посмотреть сообщение
но у меня вся "логика" приложений построена на том, что я подписываюсь на события и из них обращаюсь к vm, и по этому я не пойму как по другому-то нужно делать?(это все винформы виноваты)
В WPF есть система привязок к свойствам VM. Для свойств VM есть технология INPC. Любой изменение привязанного свойства можно обработать в VM безо всяких событий элементов UI.

В методе set свойства нужно просто обработать его изменение
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public CPSContract CurrentContract
{
    get => _currentContract;
    set
    {
        if (Set(ref _currentContract, value))
        {
            // Если свойство прошло проверку, то выполняем что нужно
            // тут, например, загружаются данные VM
            if (CurrentContract.ContractID > 0)
                _taskQueue.QueueBackgroundWorkItem(() => LoadVMData());
        }
    }
}
И класс BaseVM, в котором реализован интерфейс INPC
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
using System.ComponentModel;
using System.Runtime.CompilerServices;
 
using Services.Interfaces;
 
namespace VModels.Base
{
    public class BaseViewModel : INotifyPropertyChanged, IBaseViewModel
    {
        public event PropertyChangedEventHandler PropertyChanged;
 
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
            => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
 
        protected virtual bool Set<T>(ref T field, T value, [CallerMemberName] string PropertyName = null)
        {
            if (Equals(field, value))
                return false;
 
            field = value;
 
            OnPropertyChanged(PropertyName);
 
            return true;
        }
    }
}
1
 Аватар для firnen_dragon
25 / 25 / 4
Регистрация: 21.01.2019
Сообщений: 407
22.06.2023, 11:44  [ТС]
Andrey-MSK, тоесть в моем примере это должно выглядить вот так?
C#
1
2
3
4
5
6
7
8
9
10
        public string Text
        {
            get { return text; }
            set
            {
                text = value;
                Display(StaticClass.Processing(text));
                OnPropertyChanged(nameof(Text));
            }
        }
И еще вопрос: а если все-таки нужно через кнопку обновить коллекцию? там ведь свойства не меняются никакие
0
 Аватар для Andrey-MSK
3312 / 2199 / 387
Регистрация: 14.08.2018
Сообщений: 7,400
Записей в блоге: 4
22.06.2023, 11:57
Цитата Сообщение от firnen_dragon Посмотреть сообщение
И еще вопрос: а если все-таки нужно через кнопку обновить коллекцию? там ведь свойства не меняются никакие
Пишете команду в VM, к команде подключаете метод, который работает с коллекцией, команду привязываете к кнопке.

Добавлено через 1 минуту
firnen_dragon,
XML
1
2
<Button x:Name="btnSave" Content="Сохранить" Margin="5 5 5 2" Width="90" Height="25" 
        Command="{Binding SaveCommand}"/>
1
 Аватар для firnen_dragon
25 / 25 / 4
Регистрация: 21.01.2019
Сообщений: 407
22.06.2023, 12:12  [ТС]
Andrey-MSK, Спасибо, значит про команды почитать нужно. И все таки свойство у меня правильно написано?
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16115 / 11236 / 2887
Регистрация: 21.04.2018
Сообщений: 33,037
Записей в блоге: 2
22.06.2023, 12:23
Цитата Сообщение от firnen_dragon Посмотреть сообщение
И все таки свойство у меня правильно написано?
В первом приближении.
А в целом не желательно в свойствах добавлять логику кроме запоминания и возвращения его значения.
Для создания зависимостей обычно используются дополнительные методы.
В некоторых фреймворках они автоматически создаются посредством указания атрибутов.

Посмотрите Простые реализации для тем на форуме
В этой реализации INPC для создания зависимостей используется переопределение виртуального метода OnPropertyChanged.

Добавлено через 25 секунд
Цитата Сообщение от firnen_dragon Посмотреть сообщение
значит про команды почитать нужно.
Прочитайте темы по ссылке в подписи моего поста.
1
 Аватар для Andrey-MSK
3312 / 2199 / 387
Регистрация: 14.08.2018
Сообщений: 7,400
Записей в блоге: 4
22.06.2023, 12:26
Цитата Сообщение от firnen_dragon Посмотреть сообщение
И все таки свойство у меня правильно написано?
Ну почти Лучше как у меня сделать. Там вообще много вариантов реализаций...
Вот вариант свойства с моей реализацией INPC, тут просто отслеживаются значения, без логики как в примере выше.
C#
1
2
3
4
5
public string KKS
{
    get => _kks;
    set => Set(ref _kks, value);
}
1
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16115 / 11236 / 2887
Регистрация: 21.04.2018
Сообщений: 33,037
Записей в блоге: 2
22.06.2023, 12:36
Цитата Сообщение от firnen_dragon Посмотреть сообщение
Я б создал статический класс в котором будет происходить создание новой коллекции(или любая другая обработка коллекции) в моем понимании это и есть модель:
Кликните здесь для просмотра всего текста
Это не Модель.
Модель - это СЛОЙ приложения содержащий всю Бизнес (Доменную) Логику.
Использование ObservableCollection в Модели хоть и не противоречит прямо этому, но на практике используется крайне редко.
Причина в том, что Модель должна контролировать своё состояние. Добавление элемента в коллекцию обычно не позволяет это сделать. Поэтому обычно добавляется элемент через метод Модели, а возвращается коллекция или методом или через свойство иммутабельной коллекции (IEnumerable, IReadOnlyCollection, IReadOnlyList и др.).

Если делать через ObservableCollection, то Модель должна сама тоже её прослушивать и реагировать на изменения.
Например, такая реализация есть в локальном кеше Контекста БД в EF.

Добавлено через 30 секунд
Цитата Сообщение от Andrey-MSK Посмотреть сообщение
Лучше как у меня сделать.
Согласен. Так будет намного лучше.

Добавлено через 1 минуту
Цитата Сообщение от Andrey-MSK Посмотреть сообщение
В методе set свойства нужно просто обработать его изменение
А вот это мне не нравится.
Подойдёт только для "быстрого решения на коленке".

Добавлено через 3 минуты
firnen_dragon, мой совет: начинайте создание приложения с создания Модели в ОТДЕЛЬНОМ проекте. И только после полного её создания и отладки, приступайте к View. На этапе создания View сформируйте интерфейсы для VM. И уже после создания View реализуете интерфейсы VM тоже в ОТДЕЛЬНОМ проекте.

Пока не хватает опыта, такая последовательность реализации позволит избежать многих архитектурных ошибок.
1
 Аватар для firnen_dragon
25 / 25 / 4
Регистрация: 21.01.2019
Сообщений: 407
22.06.2023, 17:10  [ТС]
Andrey-MSK, Элд Хасп, Спасибо, пошел я смотреть для начала реализации INPC и про команды читать, потом возможно прийдется снова вернуться к этой теме.

Добавлено через 3 часа 56 минут
Элд Хасп, Andrey-MSK, Я посмотрел примеры и почитал про команды, написал по образу и подобию под задачу которую я описывал выше (с TextBox, ComboBox и Button), теперь по идее должно быть похоже на mvvm. На текущий момент есть немного вопросов, но сначала то, что я накалякал:
XAML:
Кликните здесь для просмотра всего текста

XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
    <Window.DataContext>
        <local:MainViewModel/>
    </Window.DataContext>
    <Grid>
        <TextBox x:Name="textBox" TextWrapping="Wrap" Text="{Binding Text}" Margin="10,58,274,228"/>
        <ComboBox ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem}"  x:Name="comboBox" Margin="253,58,10,228">
            <ComboBox.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Name}"/>
                </DataTemplate>
            </ComboBox.ItemTemplate>
        </ComboBox>
        <Button Command="{Binding DisplayProcessing}" x:Name="button" Content="Button" Margin="253,128,10,134"/>
    </Grid>

Что такое VMDD и почему мы не можем написать все в VM я не до конца понял, но все же их разделил.
VMDD:
Кликните здесь для просмотра всего текста

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
    public class FuzzyMainViewModel : BaseInpc
    {
 
        public ObservableCollection<Item> items;
 
        public Item SelectedItem { get; set; }
        private string text;
 
        private ICommand _displayProcessing;
 
        public ObservableCollection<Item> Items
        {
            get
            {
                return items;
            }
            set
            {
                Set(ref items, value);
            }
        }
        public string Text
        {
            get { return text; }
            set
            {
                Set(ref text, value);
            }
        }
 
        public ICommand DisplayProcessing { get { return _displayProcessing ?? (_displayProcessing = new Command(OnDisplayProcessing)); } }
 
        public virtual void OnDisplayProcessing(object Value = null) { }
 
        protected override void OnPropertyChanged(string propertyName, object oldValue, object newValue)
        {
            base.OnPropertyChanged(propertyName, oldValue, newValue);
 
            if (propertyName == nameof(Text))
                Model.DisplayProcessing(Text);
        }
 
    }

VM:
Кликните здесь для просмотра всего текста

C#
1
2
3
4
5
6
7
8
9
    public class MainViewModel : FuzzyMainViewModel
    {
        public MainViewModel()
        {
            Model.Load();
            Items = Model.Items;
        }
        public override void OnDisplayProcessing(object Value = null) { Model.DisplayProcessing(Text);} 
    }

StaticClass(в нем происходит создание новой коллекции зависимости от значения в Textbox):
Кликните здесь для просмотра всего текста
C#
1
2
3
4
5
6
7
8
9
10
        static public ObservableCollection<Item> Processing(string text)
        {
            var Collection = new ObservableCollection<Item>();
            Collection.Add(new Item() { Name = text, Category = "A", Value = 5 });
            Collection.Add(new Item() { Name = "Item4", Category = "A", Value = 7 });
            Collection.Add(new Item() { Name = "Item3", Category = "A", Value = 5 });
            Collection.Add(new Item() { Name = "Item2", Category = "B", Value = 20 });
            Collection.Add(new Item() { Name = "Item1", Category = "B", Value = 30 });
            return Collection;
        }

Модель:
Кликните здесь для просмотра всего текста
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
    public static class Model
    {
        static ObservableCollection<Item> items;
        public static ObservableCollection<Item> Items
        {
            get
            {
                return items ?? (items = new ObservableCollection<Item>());
            }
            set
            {
                items = value;
            }
        }
        public static void Load()
        {
            Items = new ObservableCollection<Item>();
            Items.Add(new Item() { Name = "Item1", Category = "A", Value = 5 });
            Items.Add(new Item() { Name = "Item2", Category = "A", Value = 7 });
            Items.Add(new Item() { Name = "Item3", Category = "A", Value = 5 });
            Items.Add(new Item() { Name = "Item4", Category = "B", Value = 20 });
            Items.Add(new Item() { Name = "Item5", Category = "B", Value = 30 });
        }
 
        public static void Display(ObservableCollection<Item> list)
        {
            Application.Current.Dispatcher.BeginInvoke(new Action(() =>
            {
                Items.Clear();
                for (int i = 0; i < list.Count; i++)
                {
                    Items.Add(list[i]);
                }
            }));
        }
        public static void DisplayProcessing(string text)
        {
            Display(StaticClass.Processing(text));
        }
    }

Вопросы:
1)правильно ли я обновляю коллекцию по измению свойства Text? возможно там тоже как-то через команду надо прокинуть это изменение?
2)Знаю, что это не совсем по wpf вопрос, а по с#, но что это вообще передается в методы модели и vm, первый раз просто такое вижу, Value - понятно, но почему равное null?
C#
1
object Value = null
3)Имеет ли вообще смысл асинхронная запись коллекции Display() в модели?
Пока что это вроде все вопросы, чет думал больше будет Ну и, если есть замечания тоже буду рад их услышать.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16115 / 11236 / 2887
Регистрация: 21.04.2018
Сообщений: 33,037
Записей в блоге: 2
22.06.2023, 20:16
Цитата Сообщение от firnen_dragon Посмотреть сообщение
Модель:
Недолжно быть Application, Dispatcher.

Я же вам писал: начинайте создание приложения с создания Модели в ОТДЕЛЬНОМ проекте. Уточню: Проекте типа "Библиотека Standard".

Добавлено через 34 секунды
Статическая Модель.... мягко говоря не приветствуется.

Добавлено через 10 минут
Цитата Сообщение от firnen_dragon Посмотреть сообщение
Что такое VMDD и почему мы не можем написать все в VM
VMDD - ViewModel с Данными Времени Разработки (Design-time data). Нужно если сложная компоновка и требуется отлаживать её с заполненными данными, а подключение модели вл время разработки нежелательно.
В этом случае в VMDD реализуются только свойства нужные для View и заполняются демонстрационными данными. Ссылки на Модель в таком случае в ней нет. Модель получает производная от VMDD "настоящая" VM и уже она записывает в свойства "настоящие" данные.

Добавлено через 35 секунд
В вашем случае разделение VMDD и VM не имеет смысла.

Добавлено через 52 секунды
Цитата Сообщение от firnen_dragon Посмотреть сообщение
StaticClass(в нем происходит создание новой коллекции зависимости от значения в Textbox):
Тоже треш какой-то.

Добавлено через 4 минуты
firnen_dragon, вот заготовка под Модель
C#
1
2
3
4
5
6
7
8
9
10
11
12
    public  class Model
    {
        private readonly List<Item> items = new()
            {
                new Item() { Name = "Item1", Category = "A", Value = 5 },
                new Item() { Name = "Item2", Category = "A", Value = 7 },
                new Item() { Name = "Item3", Category = "A", Value = 5 },
                new Item() { Name = "Item4", Category = "B", Value = 20 },
                new Item() { Name = "Item5", Category = "B", Value = 30 }
            };
        public IEnumerable<Item> GetItems() => items.Select(item => item);
    }
Добавлено через 1 минуту
Так же следует соблюдать Правила Именования.
В данном случае класс Items должен быть именован согласно его предметной области. Имена и значения это чего?

Добавлено через 6 минут
firnen_dragon, вот чуть дополнил Модель:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
    public  class Model
    {
        private readonly List<Item> items = new()
            {
                new Item() { Name = "Item1", Category = "A", Value = 5 },
                new Item() { Name = "Item2", Category = "A", Value = 7 },
                new Item() { Name = "Item3", Category = "A", Value = 5 },
                new Item() { Name = "Item4", Category = "B", Value = 20 },
                new Item() { Name = "Item5", Category = "B", Value = 30 }
            };
        public IEnumerable<Item> GetItems() => items.Select(item => item);
 
 
        public event EventHandler<IEnumerable<Item>>? ResetItems;
        public void Reset(IEnumerable<Item> items)
        {
            this.items.Clear();
            this.items.AddRange(items);
            ResetItems?.Invoke(this, GetItems());
        }
    }
1
 Аватар для firnen_dragon
25 / 25 / 4
Регистрация: 21.01.2019
Сообщений: 407
23.06.2023, 10:59  [ТС]
Элд Хасп,
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Статическая Модель.... мягко говоря не приветствуется.
Но у вас ведь тут в примере статическая модель.
Пример реализации WPF+MVVM приложения

И, если она должна быть не статической то экземпляр модели создавать нужно в vm?
Цитата Сообщение от Элд Хасп Посмотреть сообщение
вот чуть дополнил Модель
Думаю так писать мне пока рановато, для начала просто бы научиться нормально отделять слои приложения и связывать их между собой, и работать через изменения свойств, чтоб избегать таких багов как у меня с событиями происходили.
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Так же следует соблюдать Правила Именования.
В данном случае класс Items должен быть именован согласно его предметной области. Имена и значения это чего?
Это я понимаю, но так как это проект создан исключительно чтоб потренироваться я просто рандомные названия свойств сделал.

И все таки вот это вот приемлемо?
C#
1
2
3
4
5
6
7
        protected override void OnPropertyChanged(string propertyName, object oldValue, object newValue)
        {
            base.OnPropertyChanged(propertyName, oldValue, newValue);
 
            if (propertyName == nameof(Text))
                Model.DisplayProcessing(Text);
        }
Или вы тут не об этом говорили?
Цитата Сообщение от Элд Хасп Посмотреть сообщение
А в целом не желательно в свойствах добавлять логику кроме запоминания и возвращения его значения.
Для создания зависимостей обычно используются дополнительные методы.
В некоторых фреймворках они автоматически создаются посредством указания атрибутов.
0
 Аватар для Andrey-MSK
3312 / 2199 / 387
Регистрация: 14.08.2018
Сообщений: 7,400
Записей в блоге: 4
23.06.2023, 11:31
Цитата Сообщение от Элд Хасп Посмотреть сообщение
А вот это мне не нравится.
Подойдёт только для "быстрого решения на коленке".
Покажите как можно сделать по другому... Может я не так запросы в поиск отправляю, но что-то найти не могу...
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16115 / 11236 / 2887
Регистрация: 21.04.2018
Сообщений: 33,037
Записей в блоге: 2
23.06.2023, 11:43
Цитата Сообщение от firnen_dragon Посмотреть сообщение
Но у вас ведь тут в примере статическая модель.
Пример реализации WPF+MVVM приложения
Я писал эту тему когда только несколько месяцев изучал Шарп и WPF. И создана она была "по мотивам" другой, не моей темы.
Сейчас бы я так не делал.

Цитата Сообщение от firnen_dragon Посмотреть сообщение
И, если она должна быть не статической то экземпляр модели создавать нужно в vm?
Допускается.
Но в общем случае все слои и зависимости между ними задаются в App.

Цитата Сообщение от firnen_dragon Посмотреть сообщение
И все таки вот это вот приемлемо?
Да.

Цитата Сообщение от Andrey-MSK Посмотреть сообщение
Покажите как можно сделать по другому...
Например, выше показал firnen_dragon - задание зависимостей в переопределённом методе OnPropertyChanged.

Добавлено через 2 минуты
Вот здесь в реализации BaseInpc тоже есть пример: Простые реализации для тем на форуме
2
 Аватар для Andrey-MSK
3312 / 2199 / 387
Регистрация: 14.08.2018
Сообщений: 7,400
Записей в блоге: 4
23.06.2023, 11:50
Элд Хасп, То бишь в каждой VM переопределять OnPropertyChanged() и прописывать в нём логику для работы свойств?
C#
1
2
3
4
5
6
7
8
9
10
protected override void OnPropertyChanged(string propertyName, object oldValue, object newValue)
{
    base.OnPropertyChanged(propertyName, oldValue, newValue);
 
    // Проверяется имя изменившегося свойства и производятся необходимые действия
    
    // Тут пишем для всех свойств логику обработки изменений?
    if (propertyName == nameof(Number) || propertyName == nameof(Mod))
        ModNumber = Number % Mod;
}
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16115 / 11236 / 2887
Регистрация: 21.04.2018
Сообщений: 33,037
Записей в блоге: 2
23.06.2023, 11:55
Цитата Сообщение от Andrey-MSK Посмотреть сообщение
То бишь в каждой VM переопределять OnPropertyChanged() и прописывать в нём логику для работы свойств?
Я предпочитаю так.
И сколько видел фраймворков - во всех них это предпочтительный способ.
Во многих создание зависимости происходит неявно через указание атрибутов. Но суть та же: в теле свойства только получение и сохранение его значения.
2
 Аватар для Andrey-MSK
3312 / 2199 / 387
Регистрация: 14.08.2018
Сообщений: 7,400
Записей в блоге: 4
23.06.2023, 12:16
firnen_dragon,
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Но в общем случае все слои и зависимости между ними задаются в App.
Обычно это делается через DI
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private static IServiceProvider ConfigureServices()
{
    var services = new ServiceCollection();
 
    services
        .AddSingleton(Current.Configuration)
        .AddSingleton<IMainDA, MainDA>()
        .AddSingleton<IViewModelsService, ViewModelsService>()
        .AddSingleton<IWindowService, WindowService>()
        .AddSingleton<IBackgroundTaskQueue, BackgroundTaskQueue>()
        .AddSingleton<IViewModelFactory, ViewModelFactory>()
        .AddTransient<IMainWindowVM, MainWindowVM>();
 
    return services.BuildServiceProvider();
}
И при этом сборка с App имеет связи со всеми слоями Решения.
И тогда VM получает все нужные сервисы через свой конструктор
C#
1
2
3
4
5
6
7
8
9
10
11
12
public CPSContractSelectDialogVM(IWindowService windowService,
                                 IBackgroundTaskQueue taskQueue,
                                 IMainDA mainDA,
                                 IViewModelFactory viewModelFactory)
{
    _windowService = windowService;
    _taskQueue = taskQueue;
    _mainDA = mainDA;
    _viewModelFactory = viewModelFactory;
 
    IsContractSelect = false;
}
2
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
23.06.2023, 12:16
Помогаю со студенческими работами здесь

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

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

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

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

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


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru