Форум программистов, компьютерный форум, киберфорум
C#: WPF, UWP и Silverlight
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.73/15: Рейтинг темы: голосов - 15, средняя оценка - 4.73
 Аватар для ShmelVG
171 / 106 / 51
Регистрация: 27.11.2015
Сообщений: 1,269

Моментальный переход страниц назад/вперед mvvm

20.08.2019, 16:47. Показов 3343. Ответов 16
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Приложение WPF MVVM.

Многопоточное приложение.
Есть проблема, допустим есть 2 кнопки на странице вперед/назад,где после нажатия попадаем на соответствующее окно, но если к примеру нажать много раз назад и уйти пить чай, то можно заметить, как приложение будет отрабатывать 50 раз нажатие кнопок, как это предотвратить, либо сделать моментальным.
Например реализация команды назад:

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
abstract class StateVM<TParent> : BaseVM, IState<TParent>
    {
        private IAsyncCommand _goBackCommand;
        private IAsyncCommand _goForwardCommand;
 
        // Сообщает StateNavigator сохранять ли стейт в истории перемещений,
        // чтобы вернуться на него по GoBack() или GoForward()
        public abstract bool IsHistoryPart { get; }
 
        public TParent Parent { get; set; }
        public IStateNavigator<TParent> Navigator { get; set; }
 
        public IAsyncCommand GoBackCommand
        {
            get { return _goBackCommand ?? (_goBackCommand = new AsyncDelegateCommand(GoBack, CanGoBack)); }
        }
        
        public IAsyncCommand GoForwardCommand
        {
            get { return _goForwardCommand ?? (_goForwardCommand = new AsyncDelegateCommand(GoForward, CanGoForward)); }
        }
 
        protected virtual async Task GoBack()
        {
            await Navigator.GoBack();
        }
 
        protected  virtual bool CanGoBack()
        {
            return Navigator.CanGoBack;
        }
 
        protected virtual async Task GoForward()
        {
            await Navigator.GoForward();
        }
 
        protected virtual bool CanGoForward()
        {
            return Navigator.CanGoForward;
        }
По сути везде используется навигатор, к пример вперед перейти await Navigator.Navigate(new MainStateVM());

Добавлено через 1 минуту
Может запускать метод Task GoBack() в новой задаче?

Добавлено через 14 минут
Забавно то, что в дебаге всё летает как надо, а релиз нет(

Добавлено через 1 час 9 минут
Или чтобы можно было нажать на кнопку только один раз
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
20.08.2019, 16:47
Ответы с готовыми решениями:

Переход страниц назад/вперед
Есть документ в бордере &lt;ItemsControl ScrollViewer.PanningMode=&quot;Both&quot; ...

Можно ли каким-то образом скрыть кнопки назад, вперед в элементе Frame?
Нужно, чтобы сама панель с кнопками не отображалась. Свойства Frame для скрытия кнопок вроде нету. Подскажите, как можно скрыть панель с...

Проблема реализации навигации страниц через MVVM
Все привет. Смысл программы в том что бы переводить русские документы на англиские через шаблоны. Которые ты выбираешь в Combobox....

16
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16113 / 11234 / 2887
Регистрация: 21.04.2018
Сообщений: 33,035
Записей в блоге: 2
20.08.2019, 17:33
Цитата Сообщение от ShmelVG Посмотреть сообщение
можно заметить, как приложение будет отрабатывать 50 раз нажатие кнопок, как это предотвратить, либо сделать моментальным.
То есть вам надо чтобы сразу произошёл переход на нужную страницу без пролистывания промежуточных?

Если так, то вам надо создать какой-то способ перемещения сразу на нужную страницу. Navigator.GoBack();, насколько я понимаю, не позволяет "перепрыгивать" через страницы.

Должно быть что-то подобное браузеру. Нажал на стрелку переместился на одну страничку, нажал ПКМ - выбрал из истории на какую именно и перепрыгиваешь на неё.
0
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
21.08.2019, 01:24
Цитата Сообщение от ShmelVG Посмотреть сообщение
как это предотвратить
Отключать команду на время перехода.
Не знаю, что за реализацию асинхронной команды вы используете, но покопайтесь в ее свойствах: возможно, там можно запретить повторный вызов пока команда отрабатывает.
Если это ваша собственная реализация, то добавьте соответствующий функционал.
0
 Аватар для ShmelVG
171 / 106 / 51
Регистрация: 27.11.2015
Сообщений: 1,269
21.08.2019, 10:10  [ТС]
Элд Хасп, Элд Хасп,
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Navigator.GoBack();
- именно его и использовал. Я не могу отладить этот момент (т.к. в данный момент нет возможности), я не понимаю, если быстро 50 раз нажать назад, он именно 50 раз выполняет метод назад или он покидает страницу и касание попадает на новую кнопку назад и т.п. ... кнопки расположены на одном и том же месте. Очень странно что так только для релиза...Хотя в команде кроме навигатора ничего не используется... у меня есть предположение, что токгда он попадает назад , эта страница начинает заново "инициализироваться", посылать запросы, всякие проверки, из-за этого думаю долго...

Добавлено через 3 минуты
kolorotur, Элд Хасп, может проще сделать во вью модели в команде булевую переменную в начале метода - фолс, а по окончании метода к примеру тру и если тру то кнопка становится видимой, а во время выполнении команды будет неактивна, мб так получится?

Добавлено через 22 секунды
(чисто теоретически )
0
Эксперт .NET
 Аватар для novikov.ea
1855 / 1361 / 429
Регистрация: 10.06.2011
Сообщений: 2,136
21.08.2019, 10:58
Цитата Сообщение от ShmelVG Посмотреть сообщение
булевую переменную в начале метода - фолс, а по окончании метода к примеру тру и если тру то кнопка становится видимой, а во время выполнении команды будет неактивна, мб так получится?
От данной булевой переменной должно зависеть CanExecute команды. Тогда нельзя будет нажать на кнопку повторно.
0
 Аватар для ShmelVG
171 / 106 / 51
Регистрация: 27.11.2015
Сообщений: 1,269
21.08.2019, 11:10  [ТС]
novikov.ea, т.е. сделать так , как я написал, а активной её делать в CanExecute(если тру, то видна)?

Добавлено через 10 минут
novikov.ea, что-то я туплю) Вы могли бы подсказать, как сделать в этом коде:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
private IAsyncCommand _goBackCommand;
 public IAsyncCommand GoBackCommand
        {
            get { return _goBackCommand ?? (_goBackCommand = new AsyncDelegateCommand(GoBack, CanGoBack)); }
        }
protected virtual async Task GoBack()
        {
            bool enable = false;
            await Navigator.GoBack();
            enable = true;
        }
 
        protected  virtual bool CanGoBack()
        {
            return Navigator.CanGoBack;
        }
Кнопка
XML
1
2
3
4
<Button 
                Content="{Binding Path=Parent.SelectedLanguage.Phrases[......]}"
                Style="{StaticResource NavigationButtonStyle}"
                Command="{Binding Path=GoBackCommand}"/>
0
13 / 11 / 5
Регистрация: 14.09.2018
Сообщений: 88
21.08.2019, 11:17
ShmelVG, а если кнопку хакнут? А? Вы не рассматривали такое развитие событий?

Добавлено через 58 секунд
Тут хакеры пишут утилиты по активации кнопок! Почему бы не предусмотреть невозможность многократного вызова в коде? Или это обезьяний подход?

Добавлено через 1 минуту
Цитата Сообщение от novikov.ea Посмотреть сообщение
От данной булевой переменной должно зависеть CanExecute команды.
Но ведь это же как надеть на себя муляж мускулатуры и ходить хвастаться, что ты качок!
0
 Аватар для ShmelVG
171 / 106 / 51
Регистрация: 27.11.2015
Сообщений: 1,269
21.08.2019, 11:18  [ТС]
QwertyJacksonX,
Цитата Сообщение от QwertyJacksonX Посмотреть сообщение
а если кнопку хакнут?
- что именно вы подразумеваете под этим? Весь код компилируется )
Покажите пример кода, что вы имеете ввиду?
0
13 / 11 / 5
Регистрация: 14.09.2018
Сообщений: 88
21.08.2019, 11:21
Цитата Сообщение от ShmelVG Посмотреть сообщение
- что именно вы подразумеваете под этим?
Это сторонней утилитой активируют кнопку и начнут жать десятки раз.

Добавлено через 40 секунд
А так в коде напишешь невозможность это сделать даже случайно и сидишь такой гордый, улыбаешься!
0
 Аватар для ShmelVG
171 / 106 / 51
Регистрация: 27.11.2015
Сообщений: 1,269
21.08.2019, 11:32  [ТС]
QwertyJacksonX, в данном случае у них не будет возможности установить стороннюю утилиту.
Цитата Сообщение от QwertyJacksonX Посмотреть сообщение
А так в коде напишешь невозможность это сделать даже случайно и сидишь такой гордый, улыбаешься!
- окей, продемонстрируйте на примере пожалуйста

Добавлено через 1 минуту
QwertyJacksonX, вы знакомы с командой Navigator.GoBack();? У меня не будут проблемы, если злоумышленники теоретически нажимали бы её 100500+ раз
0
Эксперт .NET
 Аватар для novikov.ea
1855 / 1361 / 429
Регистрация: 10.06.2011
Сообщений: 2,136
21.08.2019, 11:46
Цитата Сообщение от QwertyJacksonX Посмотреть сообщение
Это сторонней утилитой активируют кнопку и начнут жать десятки раз.
Даже если кнопку активируют и нажмут десятки раз, команда не будет выполняться, пока её CanExecute=false.
0
 Аватар для ShmelVG
171 / 106 / 51
Регистрация: 27.11.2015
Сообщений: 1,269
21.08.2019, 11:50  [ТС]
novikov.ea, вы могли бы показать как надо написать(на примере моей команды)? Если я быстро нажимаю 2 раза, команды выполняется 2 раза
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16113 / 11234 / 2887
Регистрация: 21.04.2018
Сообщений: 33,035
Записей в блоге: 2
21.08.2019, 11:51
Цитата Сообщение от ShmelVG Посмотреть сообщение
если быстро 50 раз нажать назад, он именно 50 раз выполняет метод назад или он покидает страницу и касание попадает на новую кнопку назад
Цитата Сообщение от ShmelVG Посмотреть сообщение
сделать во вью модели в команде булевую переменную в начале метода - фолс, а по окончании метода к примеру тру и если тру то кнопка становится видимой, а во время выполнении команды будет неактивна
Я не совсем врубаюсь что вы хотите реализовать.
Изначально я подумал, что вам надо сделать сразу переход на последнюю на последнюю страницу. Но, похоже, я вас не правильно понял. Вам нужно просто сделать неактивными кнопки перехода пока не отработала команда перехода.

Если так, то попробуйте такой вариант
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
abstract class StateVM<TParent> : BaseVM, IState<TParent>
    {
        protected bool isTransition = false;
        protected virtual async Task GoBack()
        {
            if (isTransition)
                 return;
            isTransition = true;
            await Navigator.GoBack();
            isTransition = false;
        }
 
        protected  virtual bool CanGoBack()
        {
            return !isTransition && Navigator.CanGoBack;
        }
 
        protected virtual async Task GoForward()
        {
            if (isTransition)
                 return;
            isTransition = true;
            await Navigator.GoForward();
            isTransition = false;
        }
 
        protected virtual bool CanGoForward()
        {
            return !isTransition && Navigator.CanGoForward;
        }
Добавлено через 34 секунды
Пишу здесь в редакторе сообщений - могут быть мелкие ошибки.
1
Эксперт .NET
 Аватар для novikov.ea
1855 / 1361 / 429
Регистрация: 10.06.2011
Сообщений: 2,136
21.08.2019, 12:03
Цитата Сообщение от ShmelVG Посмотреть сообщение
вы могли бы показать как надо написать
Что-то типа этого
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
private bool isTransitionProcessing = false;
 
private ICommand _goCommand;
 
public ICommand GoCommand
{
    get { return _goCommand ?? (_goCommand = new AsyncDelegateCommand(Go, CanGo)); }
}
 
private async Task Go()
{
    isTransitionProcessing = true;
    await Navigator.GoForward();
    isTransitionProcessing = false;
}
 
private bool CanGo()
{
    return !isTransitionProcessing && Navigator.CanGoForward; 
}
1
 Аватар для ShmelVG
171 / 106 / 51
Регистрация: 27.11.2015
Сообщений: 1,269
21.08.2019, 12:11  [ТС]
novikov.ea, Элд Хасп, спасибо, я делал что-то похожее , но эффекта нет((..Я сейчас протестировал, к примеру если дойти до 4 страницы и нажать очень быстро отмену 10 раз, он вернется сначала на 3, потом на 2, потом на 1 (почему-то) на 2. А должен быстро нажать отмену на 4 стр 10 раз и вернуться только на 3 страницу

Добавлено через 25 секунд
или это принцип работы самой команды Navigator.GoBack(); ?

Добавлено через 1 минуту
наверное в моём случае придётся ручками писать вместо данной команды именно переход на нужную страницу по имени, а не с помощью этой команды(
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16113 / 11234 / 2887
Регистрация: 21.04.2018
Сообщений: 33,035
Записей в блоге: 2
21.08.2019, 12:22
Цитата Сообщение от ShmelVG Посмотреть сообщение
А должен быстро нажать отмену на 4 стр 10 раз и вернуться только на 3 страницу
Нет.
По-моему, это последствия много поточности.
При изменении состояния команды из других потоков может не срабатывать валидация её состояния.
Для принудительной валидации в команду надо добавить метод аналогичный Invalidate() в классе релай команд Новая реализация RelayCommand с исправлениями от proa33 и kolorotur.

Или перейдите на синхронные команды в котором только в необходимых местах вызываются другие потоки.

Ещё есть вариант использовать вместо поля isTransitionProcessing аналогичное свойство к которому привязать IsEnabled кнопок. Для WPF INPC приводится к основному потоку. Но если у вас UWP, то об этом надо позаботиться самостоятельно.
1
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16113 / 11234 / 2887
Регистрация: 21.04.2018
Сообщений: 33,035
Записей в блоге: 2
21.08.2019, 21:12
ShmelVG, посмотрите демонстрационный пример работы метода Invalidate при использовании асинхронного метода в команде
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
    public class TestInvalidateTaskVM : OnPropertyChangedClass
    {
        private string _message;
        private bool _isCanInvalidate;
        private bool _isEnabled;
        private RelayCommand _taskRunCommand;
 
        public string Message { get => _message; set { _message = value; OnPropertyChanged(); } }
        public bool IsCanInvalidate { get => _isCanInvalidate; set { _isCanInvalidate = value; OnPropertyChanged(); } }
 
        public bool IsEnabled
        {
            get => _isEnabled;
            set
            {
                _isEnabled = value;
                OnPropertyChanged();
                Message = IsEnabled ? "Активна" : "Не активна";
                if (IsCanInvalidate)
                    TaskRunCommand.Invalidate();
            }
        }
 
        public RelayCommand TaskRunCommand => _taskRunCommand ?? (_taskRunCommand = new RelayCommand(TaskRunMetodAsync, p => IsEnabled));
 
        private async void TaskRunMetodAsync(object parameter)
        {
            await Task.Run(() => TaskRunMetod(parameter)); ;
        }
 
        private void TaskRunMetod(object parameter)
        {
            IsEnabled = false;
            Thread.Sleep(5000);
            IsEnabled = true;
        }
        public TestInvalidateTaskVM() => IsEnabled = true;
    }
XML
1
2
3
4
5
6
7
8
9
    <StackPanel>
        <StackPanel.DataContext>
            <local:TestInvalidateTaskVM/>
        </StackPanel.DataContext>
        <TextBlock Text="{Binding Message}"/>
        <TextBlock Text="{Binding IsEnabled}"/>
        <CheckBox Content="Использовать Invalidate" IsChecked="{Binding IsCanInvalidate}"/>
        <Button Content="Эмуляция задержки в Task" Command="{Binding TaskRunCommand}"/>
    </StackPanel>
Добавлено через 7 минут
Если же использовать привязку Button.IsEnabled, то вызов метода Invalidate не нужен
XML
1
2
        <Button Content="Эмуляция задержки в Task" Command="{Binding TaskRunCommand}"
                IsEnabled="{Binding IsEnabled}"/>
C#
1
        public RelayCommand TaskRunCommand => _taskRunCommand ?? (_taskRunCommand = new RelayCommand(TaskRunMetodAsync));
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
21.08.2019, 21:12
Помогаю со студенческими работами здесь

WPF, MVVM, Переход из одного окна в другое
Здравствуйте. Пишу курсовой проект &quot;Электронный менеджер&quot;. И застопорился в самом начале. Подразумевается, что моим приложением будут...

Плавный переход страниц во Frame
Всем привет! кто знает как сделать чтобы при переходе на другую страницу во фрейме происходил эффект плавного перелистывания страниц ...

Как сделать случайный переход на одну из диапазона страниц
Подскажите, пожалуйста, как сделать случайный переход на одну из диапазона страниц.

Как можно настроить переход по кнопкам вперед назад на созданной форме?
Подскажите пожалуйста, как можно настроить переход по кнопкам вперед назад на созданной форме в эксель?

Эксель, настроить переход вперед/назад по таблице при заполении данных
Помогите пожалуйста, немогу настроить переход вперед/назад по таблице при заполении данных, ввожу и в итоге переходит на другую страницу ...


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

Или воспользуйтесь поиском по форуму:
17
Ответ Создать тему
Новые блоги и статьи
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 . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
Фото: Daniel Greenwood
kumehtar 13.11.2025
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru