Форум программистов, компьютерный форум, киберфорум
C#: WPF, UWP и Silverlight
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
5 / 3 / 2
Регистрация: 02.07.2017
Сообщений: 112
WPF

Избыточные пересчеты переменной/метода

19.09.2024, 18:45. Показов 442. Ответов 3
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Всем привет!

Подскажите как избавиться от избыточных пересчетов переменных/методов.

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

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Person
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Surname { get; set; }
        public int Age { get; set; }
        public DateTime CreatedOn { get; set; }
        public DateTime UpdatedOn { get; set; }
 
        public Person()
        {
            CreatedOn = DateTime.Now;
            UpdatedOn = DateTime.Now;
        }
    }


View
Кликните здесь для просмотра всего текста
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<Window.Resources>
        <BooleanToVisibilityConverter x:Key="VisibleIfTrueConverter" />
    </Window.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <TextBlock Text="Имя" />
        <TextBox Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}" Grid.Column="1"/>
        <TextBlock Text="Фамилия" Grid.Row="1" />
        <TextBox Text="{Binding Surname, UpdateSourceTrigger=PropertyChanged}" Grid.Row="1" Grid.Column="1"/>
        <TextBlock Text="Возраст" Grid.Row="2" />
        <TextBox Text="{Binding Age, UpdateSourceTrigger=PropertyChanged}" Grid.Row="2" Grid.Column="1"/>
        <StackPanel Orientation="Horizontal" Grid.Row="3" Grid.ColumnSpan="2" Margin="5">
            <Button Content="Добавить" Command="{Binding AddPersonCommand}"
                    CommandParameter="Add"
                    Margin="5,0"/>
            <Button Content="Заменить" Command="{Binding AddPersonCommand}" 
                    CommandParameter="Edit"
                    Margin="5,0" Visibility="{Binding IsChanged, Converter={StaticResource VisibleIfTrueConverter}}" />
        </StackPanel>
        <TextBlock Margin="5" VerticalAlignment="Center" Grid.Row="4" Grid.ColumnSpan="2">
            <TextBlock.Text>
                <MultiBinding StringFormat="Запись добавлена: {0:dd.MM.yyyy HH:hh:ss}; изменена: {0:dd.MM.yyyy HH:hh:ss}">
                    <Binding Path="CreatedOn"/>
                    <Binding Path="UpdatedOn"/>
                </MultiBinding>
            </TextBlock.Text>
        </TextBlock>
        <DataGrid Grid.Row="5" Grid.ColumnSpan="2" CanUserAddRows="False" IsReadOnly="True" AutoGenerateColumns="False"
            ItemsSource="{Binding People, UpdateSourceTrigger=PropertyChanged}" SelectedItem="{Binding SelectedPerson}" >
            <DataGrid.Columns>
                <DataGridTextColumn Header="Фамилия" Binding="{Binding Surname}" />
                <DataGridTextColumn Header="Имя" Binding="{Binding Name}" />
                <DataGridTextColumn Header="Возраст" Binding="{Binding Age}" />
            </DataGrid.Columns>
        </DataGrid>
    </Grid>


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
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
class PersonVM : BaseInpc
    {
        public PersonVM()
        {
            People = new ObservableCollection<Person>
            {
                new Person() { Id = 0, Name="Ivan", Surname="Ivanov", Age=33 },
                new Person() { Id = 1, Name="Petr", Surname="Petrov", Age=22 }
            };
        }
        public ObservableCollection<Person> People { get; private set; }
 
        private Person _selectedPerson;
        public Person SelectedPerson
        {
            get { return _selectedPerson; }
            set
            {
                _selectedPerson = value; RaisePropertyChanged();
                SetCurrentVulues();
            }
        }
 
        private string _name;
        public string Name
        {
            get { return _name; }
            set
            {
                _name = value; 
                RaisePropertyChanged();
                RaisePropertyChanged("IsChanged");
            }
        }
        private string _surname;
        public string Surname
        {
            get { return _surname; }
            set
            {
                _surname = value;
                RaisePropertyChanged();
                RaisePropertyChanged("IsChanged");
            }
        }
        private int _age;
        public int Age
        {
            get { return _age; }
            set
            {
                _age = value; RaisePropertyChanged();
                RaisePropertyChanged("IsChanged");
            }
        }
        private DateTime _createdOn;
        public DateTime CreatedOn
        {
            get { return _createdOn; }
            set { _createdOn = value; RaisePropertyChanged(); }
        }
        private DateTime _updatedOn;
        public DateTime UpdatedOn
        {
            get { return _updatedOn; }
            set { _updatedOn = value; RaisePropertyChanged(); }
        }
        public bool IsChanged
        {
            get
            {
                if (SelectedPerson == null)
                {
                    return false;
                }
                if (SelectedPerson.Surname == Surname &&
                    SelectedPerson.Name == Name &&
                    SelectedPerson.Age == Age)
                {
                    return false;
                }
                return true;
            }
        }
 
        private RelayCommand _addPersonCommand;
        public RelayCommand AddPersonCommand => _addPersonCommand ?? (_addPersonCommand = new RelayCommand(AddPerson));
        private void AddPerson(object parameter)
        {
            if (!string.IsNullOrEmpty(Surname) && !string.IsNullOrEmpty(Name))
            {
                switch ((string)parameter)
                {
                    case "Add":
                        int nextId = People.Select(x => x.Id).Max() + 1;
                        People.Add(new Person() { Id = nextId, Surname = this.Surname, Name = this.Name, Age = this.Age });
                        SelectedPerson = People[nextId];
                        break;
                    case "Edit":
                        foreach (Person p in People)
                        {
                            if (p.Id == SelectedPerson.Id)
                            {
                                p.Surname = Surname;
                                p.Name = Name;
                                p.Age = Age;
                                p.UpdatedOn = DateTime.Now;
                                SelectedPerson = p;
                                break;
                            }
                        }
                        break;
                }
            }
        }
 
        private void SetCurrentVulues()
        {
            Surname = SelectedPerson.Surname;
            Name = SelectedPerson.Name;
            Age = SelectedPerson.Age;
            CreatedOn = SelectedPerson.CreatedOn;
            UpdatedOn = SelectedPerson.UpdatedOn;
            RaisePropertyChanged("IsChanged");
        }
        
    }


В примере есть переменная IsChanged пирвязанная к свойству видимости элемента кнопки "Заменить".
При изменении переменных отдельно, в текстбоксах к которым они привязаны, расчет IsChanged происходит один раз, как и надо.
А при изменении SelectedPerson - пересчитывается 4 раза, 3 при присвоении привязанных переменных и один раз при изменении SelectedPerson.
Вопрос в том, как избавиться от лишних пересчетов. Например отписаться от RaisePropertyChanged этих переменных перед присвоением и подписаться после или есть другие решения?
Либо (если по другому никак) вообще надо перестроить проект?
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
19.09.2024, 18:45
Ответы с готовыми решениями:

Присвоение переменной одного метода значения из другого метода
Есть метод А(), в которой в переменную int a присваивается 34; И есть метод В(), в которой в переменную int b присваивается А().а :) ...

Вызов переменной метода A из метода В
Добрый день. Подскажите как происходит вызов Например даны два класс А и В, в каждом классе есть Метод 1 и метод 2 class A { void...

Обращение к переменной метода из другого метода
public class Solution { public static void main(String args) throws Exception { readText(); rectangle(); ...

3
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16115 / 11236 / 2887
Регистрация: 21.04.2018
Сообщений: 33,037
Записей в блоге: 2
19.09.2024, 23:11
Цитата Сообщение от Beginnner Посмотреть сообщение
Model
Это не модель, а какая-то сущность. Скорее даже DTO.

Цитата Сообщение от Beginnner Посмотреть сообщение
Вопрос в том, как избавиться от лишних пересчетов.
И чем они мешают?
В данном случае, усложнение логики не стоит результата.

Цитата Сообщение от Beginnner Посмотреть сообщение
вообще надо перестроить проект?
Я бы посоветовал изменить реализацию свойств и создания зависимостей.
Вы же используете BaseInpc отсюда: Простые реализации для тем на форуме?
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
    public class Person
    {
        private string name = string.Empty;
        private string surname = string.Empty;
 
        public int Id { get; set; }
        public string Name { get => name; set => name = value ?? string.Empty; }
        public string Surname { get => surname; set => surname = value ?? string.Empty; }
        public int Age { get; set; }
        public DateTime CreatedOn { get; set; } = DateTime.Now;
        public DateTime UpdatedOn { get; set; } = DateTime.Now;
 
    }
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
130
131
132
133
134
135
136
137
138
    public class PersonVM : BaseInpc
    {
        public PersonVM()
        {
            People = new ObservableCollection<Person>
            {
                // Нулевой ID в большинстве фреймворках бывает у новых сущностей,
                // которые не сохранены.
                new Person() { Id = /*0*/ 1, Name="Ivan", Surname="Ivanov", Age=33 },
                new Person() { Id = /*1*/ 2, Name="Petr", Surname="Petrov", Age=22 }
            };
        }
        public ObservableCollection<Person> People { get; /*private set; */}
 
        private Person? _selectedPerson;
        public Person? SelectedPerson
        {
            get => _selectedPerson;
            set => Set(ref _selectedPerson, value);
        }
 
        private string _name = string.Empty;
        public string Name
        {
            get => _name;
            set => Set(ref _name, value ?? string.Empty);
        }
 
        private string _surname = string.Empty;
        public string Surname
        {
            get => _surname;
            set => Set(ref _surname, value ?? string.Empty);
        }
        private int _age;
        public int Age
        {
            get => _age;
            set => Set(ref _age, value);
        }
 
        private DateTime _createdOn;
        public DateTime CreatedOn
        {
            get => _createdOn;
            set => Set(ref _createdOn, value);
        }
 
        private DateTime _updatedOn;
        public DateTime UpdatedOn
        {
            get => _updatedOn;
            set => Set(ref _updatedOn, value);
        }
 
        private bool _isChanged;
        public bool IsChanged
        {
            get => _isChanged;
            set => Set(ref _isChanged, value);
        }
 
        private RelayCommand? _addPersonCommand;
        public RelayCommand AddPersonCommand => _addPersonCommand ?? (_addPersonCommand = new RelayCommand(AddPerson));
        private void AddPerson(object parameter)
        {
            if (!string.IsNullOrEmpty(Surname) && !string.IsNullOrEmpty(Name))
            {
                switch ((string)parameter)
                {
                    case "Add":
                        int nextId = People.Select(x => x.Id).Max() + 1;
                        People.Add(new Person() { Id = nextId, Surname = this.Surname, Name = this.Name, Age = this.Age });
                        // SelectedPerson = People[nextId]; Может выдать исключение.
                        SelectedPerson = People[^1];
                        break;
 
                    case "Edit":
                        //foreach (Person p in People)
                        //{
                        //    if (p.Id == SelectedPerson.Id)
                        //    {
                        //        p.Surname = Surname;
                        //        p.Name = Name;
                        //        p.Age = Age;
                        //        p.UpdatedOn = DateTime.Now;
                        //        SelectedPerson = p;
                        //        break;
                        //    }
                        //}
                        // Зачем цикл, если нужная сущность и так выбрана?
 
                        if (SelectedPerson is not null)
                        {
                            SelectedPerson.Surname = Surname;
                            SelectedPerson.Name = Name;
                            SelectedPerson.Age = Age;
                            SelectedPerson.UpdatedOn = DateTime.Now;
                        }
 
                        break;
                }
            }
        }
 
        //private void SetCurrentVulues()
        //{
        //    Surname = SelectedPerson.Surname;
        //    Name = SelectedPerson.Name;
        //    Age = SelectedPerson.Age;
        //    CreatedOn = SelectedPerson.CreatedOn;
        //    UpdatedOn = SelectedPerson.UpdatedOn;
        //    RaisePropertyChanged("IsChanged");
        //}
 
        protected override void OnPropertyChanged(string propertyName, object oldValue, object newValue)
        {
            base.OnPropertyChanged(propertyName, oldValue, newValue);
 
            if (propertyName is nameof(Surname) or nameof(Name) or nameof(Age))
            {
                IsChanged = !
                    (SelectedPerson is null ||
                    SelectedPerson.Surname == Surname &&
                    SelectedPerson.Name == Name &&
                    SelectedPerson.Age == Age);
            }
 
            if (propertyName is nameof(SelectedPerson))
            {
                Surname = SelectedPerson?.Surname!;
                Name = SelectedPerson?.Name!;
                Age = SelectedPerson?.Age ?? 0;
                CreatedOn = SelectedPerson?.CreatedOn ?? DateTime.Now;
                UpdatedOn = SelectedPerson?.UpdatedOn ?? DateTime.Now;
            }
        }
    }
1
5 / 3 / 2
Регистрация: 02.07.2017
Сообщений: 112
23.09.2024, 19:13  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
И чем они мешают?
В данном случае, усложнение логики не стоит результата.
Согласен, в данном случае не мешают.
Просто представил большой класс, где таких пересчетов будет не 2-3, а x*[много]^2!.
Вот и возник интерес, как этого можно избежать.
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Вы же используете BaseInpc отсюда:
Верно.
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Я бы посоветовал изменить реализацию свойств и создания зависимостей.
Спасибо за интересный подход!
Но если реализовать кнопку отмены внесенных изменений, все равно же придется использовать метод SetCurrentVаlues() в команде этой кнопки.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16115 / 11236 / 2887
Регистрация: 21.04.2018
Сообщений: 33,037
Записей в блоге: 2
23.09.2024, 21:05
Цитата Сообщение от Beginnner Посмотреть сообщение
Но если реализовать кнопку отмены внесенных изменений, все равно же придется использовать метод SetCurrentVаlues() в команде этой кнопки.
Команда - это МЕТОД. У метода, естественно, есть какое-то тело с логикой.
А вот у свойств нежелательно помещать сложную логику в тело. Создание зависимостей лучше вынести. Всё таки основное назначение свойства - хранить значение. И дополнительная логика усложняет понимание кода, увеличивает вероятность ошибок.

Цитата Сообщение от Beginnner Посмотреть сообщение
Просто представил большой класс, где таких пересчетов будет не 2-3, а x*[много]^2!.
Если это действительно проблема, которая реально в тестах значительно замедляет GUI - тогда, конечно, можно придумать множество решений. Но это должна быть именно реальная проблема, решение которой оправдает кучу дополнительного, довольно запутанного кода.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
23.09.2024, 21:05
Помогаю со студенческими работами здесь

Вызов переменной метода из другого метода
class A(): def m(self): number = x #переменный параметр - номер заявки, определяется во время выполнения метода ...

Вызов переменной из другого метода или как перемножить результат с новой переменной
Здравствуйте, подскажите пожалуйста как доделать После перемножения двух матриц, надо создать еще задачу перемножения результата с...

Использование имени метода/переменной, указанного в переменной String
public class Oll { String FishR = {&quot;R&quot;,&quot;U&quot;,&quot;Rb&quot;,&quot;U&quot;,&quot;R&quot;,&quot;U&quot;,&quot;U&quot;,&quot;Rb&quot;}; String FishL = {&quot;Lb&quot;,&quot;Ub&quot;,&quot;L&quot;,&quot;Ub&quot;,&quot;Lb&quot;,&quot;U&quot;,&quot;U&quot;,&quot;L&quot;}; ...

Пересчеты при изменении тарифного плана
Создание компьютерного приложение для расчётов пересчета при изменения тарифного плана.

Апы и пересчеты у регионов идут с запаздыванием?
Вот наблюдаю, что народ часто говорит про Апы и пересчеты Тиц в Яндексе и Гугле. Они происходят одновременно для всех, или по очереди идет?...


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

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