Форум программистов, компьютерный форум, киберфорум
Hugonavy
Войти
Регистрация
Восстановить пароль
Оценить эту запись

WPF.MaterialDesign - основы MVVM реализации (DialogHost и Диалоговые окна)

Запись от Hugonavy размещена 17.06.2021 в 11:42
Обновил(-а) Hugonavy 17.06.2021 в 19:27

Сегодня я уже перейду к сути изначально задуманного - MVVM реализация библиотеки MaterialDesign в WPF. Идея эта возникла в тот момент, когда на этапе формирования своих решений с использованием данной библиотеки я столкнулся с тем, что никаких "готовых решений из коробки" в интернете практически не смог найти.

И рассмотрим мы использование диалоговых окон

MaterialDesign предоставляет удобную возможность формирования диалоговых окон (далее - ДО) для различных вариантов взаимодействия с пользователем.
Основным элементом здесь является DialogHost, представляющий из себя контейнер, в котором можно разместить все, что угодно. При вызове ДО, весь контент, расположенный в данном контейнере, будет затемнен и поверх будет показывать само ДО.
XML
1
2
3
4
5
    <materialDesign:DialogHost x:Name="MainDialogHost" 
                               Identifier="MainDialogHostId"
                               IsOpen="{Binding IsDialogOpen}" >
 
    </materialDesign:DialogHost>
IsDialogOpen переменная типа bool, при помощи которой мы задает открытие/закрытие ДО.
Identifier - идентификатор элемента DialogHost, в котором мы хотим открыть ДО. Очевидно, что их может быть больше 1.

Тут стоит отметить, что в настоящий момент библиотека не "хочет" воспринимать автоматические размеры, так широко используемые в WPF. Данную проблему я решил благодаря коллегам по данному форуму. Может быть реализация не самая идеальная, но она работает: в основном окне приложения добавлено отслеживание событие изменения размеров SizeChanged, а в CB окна добавлена следующая конструкция:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public partial class MainWindow : Window
    {
        
        public MainWindow()
        {
            InitializeComponent();
            DataContext = new MainWindowVM();
        }
 
        private void Window_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            MainDialogHost.Height = e.NewSize.Height - 37;
            MainDialogHost.Width = e.NewSize.Width - 15;
        }
    }
Теперь переместимся в ViewModel. Сразу отмечу, что реализация INotifyPropertyChanged тут обязательна.
Основные переменные, необходимые для работы компонентов библиотеки представлены ниже:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
        #region DialogHostParameters
        /// <summary>
        /// Идентификатор DialogHost
        /// </summary>
        private const string DialogHostId = "MainDialogHostId";
        /// <summary>
        /// Переменная, в которую мы грузим UC самого ДО
        /// </summary>
        private UserControl DialogControl;
        /// <summary>
        /// Состояние диалогового окна
        /// </summary>
        public bool IsDialogOpen
        {
            get => _isDialogOpen;
            set
            {
                _isDialogOpen = value;
                OnPropertyChanged();
            }
        }
        private bool _isDialogOpen;
        #endregion
Метод открытия ДО
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
        #region ShowLoadingDialog
        /// <summary>
        /// Диалоговое окно загрузки
        /// </summary>
        public async void ShowLoadingDialog()
        {
            //Исключаем возможность "двойственного" открытия ДО
            DialogClose();
            DialogControl = new LoadingUC();
            await DialogHost.Show(DialogControl, DialogHostId);
            await Task.Delay(TimeSpan.FromSeconds(2));
        }
        #endregion
 
        public void DialogClose()
        {
            IsDialogOpen = false;
        }
LoadingUC - очень простенькое окошко ожидания загрузки
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<UserControl x:Class="TestApp.Dialogs.LoadingUC"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:TestApp.Dialogs"
             xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
             mc:Ignorable="d" 
             d:DesignHeight="200" d:DesignWidth="200">
    <StackPanel Orientation="Vertical"
                Margin="16" Width="120" Height="120"
                VerticalAlignment="Center">
        <ProgressBar
            Style="{DynamicResource MaterialDesignCircularProgressBar}"
            VerticalAlignment="Center"
            Width="30" Margin="30"
            IsIndeterminate="True"
            Value="0" />
        <TextBlock Text="Загрузка" TextAlignment="Center" />
    </StackPanel>
</UserControl>
Очевидно, что переменной DialogControl может быть присвоено что-то более сложное, со своей VM. В случае отсутствия у ДО своей VM, к элементам можно обратиться из текущей VM с DialogHost (команды, Binding).

Теперь, при необходимости ожидания пользователем загрузки какого-то продолжительного процесса, можно выводить ДО загрузки:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
        public async void GetLongAction()
        {
            ShowLoadingDialog();
            int result = await Task.Run(() => GetCalculation());
            DialogClose();
            //Присвоить result какой-нибудь переменной
        }
 
        private int GetCalculation()
        {
            //Какой-то сложный расчет
            return result;
        }
На этом на сегодня все, надеюсь материал кому-нибудь да пригодится
Размещено в Без категории
Показов 491 Комментарии 0
Всего комментариев 0
Комментарии
 
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.