Сценарий применения
Программа WPF была разработана с использованием Prism 8, а кодировка выполнена в форме MVVM. Когда программа запустится, сначала войдите в интерфейс входа для выполнения аутентификации. После успешной аутентификации откроется главное окно программы.
Идея реализации проекта
После того, как программный фреймворк WPF собран, в программе сохраняется Shell.xaml, что эквивалентно единственной стадии исполнителя. Форма входа в систему (далее именуемая LoginView) и основная форма компоновки программы (далее именуемая MainView) соответственно управляются IRegionManager, и представления последовательно воспроизводятся в разное время по мере необходимости. Все операции выполняются с помощью соответствующего кода ViewModel.
- При запуске программы оболочка активирует
LoginViewчерез ViewModel и с помощью методаAdd RegionManager. После операции входа в систему отправляется сообщение loginState message. Сообщение отправляется через пользовательский класс отправки сообщений и подписки (определенный в программе:LoginSentEvent). - Оболочка принимает
loginState, переданноеLoginSentEven, для получения сообщения об успешном входе в систему. Если вход в систему прошел успешно, используйте метод деактивацииRegionManager, чтобы сделатьLoginViewнеактивным. Используйте метод добавления, чтобы активировать представлениеMainView. Если авторизация не увенчается успехом, View не поменяется, и останется на странице ввода логина. IdentityиPrincipalобъекты. Документация , Пример использования. В .NET объектыIdentityиPrincipalтесно связаны с безопасностью. ОбъектIdentityпредставляет идентификатор пользователя и метод, используемый для аутентификации пользователя. ОбъектPrincipal, с другой стороны, представляет контекст безопасности пользователя, от имени которого выполняется код, включая идентификатор этого пользователя (Identity).В C# вы можете получить доступ к объектуIdentityчерез интерфейсSystem.Security.Principal.IIdentity, который определяет базовую функциональность объекта идентификации. Доступ к объектуPrincipalвозможен черезSystem.Security.Principal.IPrincipalинтерфейс, который определяет базовую функциональность principal объекта.Вы можете использовать эти объекты для аутентификации пользователей и выполнения проверок авторизации в вашем приложении. Оба объекта могут быть использованы в приложении для аутентификации пользователей и создания контекстов безопасности для пользовательских сеансов. МодульSessionAuthenticationModuleхранит маркер безопасности, участника, идентификаторы в файле cookie и кэше в памяти, чтобы избежать повторных вызовов службы аутентификации.
Основная реализация проекта
Процедура создания программы Prism описываться не будет. Это не является предметом внимания данной статьи.
1.Логика взаимодействия App.xaml
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | public partial class App { protected override Window CreateShell() { return Container.Resolve<Shell>(); } protected override void RegisterTypes(IContainerRegistry containerRegistry) { containerRegistry.RegisterSingleton<IAuthenticationService, AuthenticationService>(); } protected override void OnStartup(StartupEventArgs e) { UserPrincipial userPrincipial = new UserPrincipial(); AppDomain.CurrentDomain.SetThreadPrincipal(userPrincipial); base.OnStartup(e); } } |
2. Shell.xaml View
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | <Window x:Class="LoginRoleApp.Views.Shell" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:prism="http://prismlibrary.com/" xmlns:local="clr-namespace:LoginRoleApp.Views" prism:ViewModelLocator.AutoWireViewModel="True" xmlns:i="http://schemas.microsoft.com/xaml/behaviors" WindowStartupLocation="CenterScreen" mc:Ignorable="d" Title="{Binding Title}" Height="450" Width="800"> <i:Interaction.Triggers> <i:EventTrigger EventName="Loaded"> <i:InvokeCommandAction Command="{Binding LoadDataCommand}"/> </i:EventTrigger> </i:Interaction.Triggers> <Grid> <ContentControl prism:RegionManager.RegionName ="MainRegion"/> </Grid> </Window> |
Shell.xaml использует EventTrigger для привязки метода LoadDataCommand путем ссылки на System.Windows.Interactivity, так что он может выполнять соответствующие операции при реализации представления, загруженного в VM
3. Shell ViewModel
Метод loaddata() запускается после загрузки представления и выполняет несколько действий:
1.MainRegion зарегистрирован
2.Созданы экземпляры Login и MainWindow,
3.Для активации добавлен LoginView.
4. EventAggregator используется для принятия сообщения о входе в систему и реализации метода обработки сообщений.
| 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 | public class ShellViewModel:BindableBase { private IEventAggregator _eventAggregator; IContainerExtension _container; private IRegionManager _regionManager; private IRegion _region; private Login loginView; private Main mainView; private string _title; public string Title { get { return _title; } set { SetProperty(ref _title, value); } } private DelegateCommand _loadDataCommand; public DelegateCommand LoadDataCommand => _loadDataCommand ?? (_loadDataCommand = new DelegateCommand(ExecuteLoadDataCommand )); public ShellViewModel(IRegionManager regionManager, IContainerExtension container,IEventAggregator aggregator) { _regionManager = regionManager; _container = container; _eventAggregator = aggregator; _eventAggregator.GetEvent<LoginSentEvent>().Subscribe(MessageReceived); } void MessageReceived(bool loginState) { if (loginState) { _region.Deactivate(loginView); mainView = _container.Resolve<Main>(); _region.Add(mainView); Title = "Now is the main form of the program"; } else { _region.Deactivate(mainView); Title = "User Login"; _region.Activate(loginView); } } void ExecuteLoadDataCommand() { _region = _regionManager.Regions["MainRegion"]; loginView = _container.Resolve<Login>(); Title = "User Login"; _region.Add(loginView); } } |
4. Класс публикации и подписки событий входа в систему
| 1 2 3 4 | public class LoginSentEvent : PubSubEvent<bool> { } |
5. Login /LoginViewModel
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | <UserControl x:Class="LoginRoleApp.Views.Login" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:prism="http://prismlibrary.com/" prism:ViewModelLocator.AutoWireViewModel="True"> <Grid Margin="30"> <Grid.RowDefinitions> <RowDefinition Height="0.8*"/> <RowDefinition Height="0.7*"/> </Grid.RowDefinitions> <DockPanel Grid.Row="1" Width="300"> <StackPanel Margin="30 10 30 0" DockPanel.Dock="Top"> <TextBlock Text="{Binding Message}" Foreground="Red" FontSize="10"/> <TextBlock Text="Войдите в свой аккаунт" FontFamily="Arial Black" HorizontalAlignment="Center" FontSize="17" FontWeight="Bold"/> <TextBox Text="{Binding Login}" Margin="0 20 0 0" /> <PasswordBox Name="password" Margin="0 20 0 0" /> <Button Command="{Binding LoginCommand}" CommandParameter="{Binding ElementName=password}" Content="Войти" Margin="10,20,0,0" Width="180"/> </StackPanel> </DockPanel> </Grid> </UserControl> |
VM
| 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 | public class LoginViewModel : BindableBase { private IEventAggregator _eventAggregator; private IAuthenticationService _authentication; private string _login; public string Login { get { return _login; } set { SetProperty(ref _login, value); } } private string message = ""; public string Message { get { return message; } set { SetProperty(ref message, value); } } public LoginViewModel(IEventAggregator aggregator,IAuthenticationService authentication) { _eventAggregator = aggregator; _authentication = authentication; } private DelegateCommand<PasswordBox> _loginCommand; public DelegateCommand<PasswordBox> LoginCommand => _loginCommand ?? (_loginCommand = new DelegateCommand<PasswordBox>(ExecuteLoginCommand)); void ExecuteLoginCommand(PasswordBox password) { try { var user = _authentication.AuthenticateUser(Login, password.Password); UserPrincipial userPrincipial = Thread.CurrentPrincipal as UserPrincipial; if (userPrincipial == null) throw new ArgumentException("Не зарегистрирован пользователь по умолчанию!"); userPrincipial.UserIdentity = new UserIdentity(user.Login,user.FIO,user.Role.ToString()); Login = ""; password.Password = ""; _eventAggregator.GetEvent<LoginSentEvent>().Publish(true); } catch (Exception ex) { Message = ex.Message; } } } |
После входа в систему с помощью кнопки «Войти», отправляется сообщение через _eventAggregator.GetEvent<LoginSentEvent>().Publish(true);
После того, как ShellViewModel принимает сообщение, вызывается метод MessageReceived, который скрывает представление входа в систему и активирует основное представление.
MainWindow не имеет к этому никакого отношения, это элемент управления окном UserControl
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <UserControl x:Class="LoginRoleApp.Views.Main" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:prism="http://prismlibrary.com/" xmlns:local="clr-namespace:LoginRoleApp.Common" prism:ViewModelLocator.AutoWireViewModel="True"> <UserControl.Resources> <local:RoleToVisibilityConverter x:Key="RoleToVisibilityConverter" /> </UserControl.Resources> <StackPanel> <TextBlock Text="{Binding UserAuth}"/> <TextBlock Text="{Binding UserRole}"/> <TextBlock Text="Этот текст только для администратора" Foreground="Green" Visibility="{Binding UserRole, Converter={StaticResource RoleToVisibilityConverter}, ConverterParameter=Администратор}"/> <Button Command="{Binding LogoutCmd}" Content="Выйти" Margin="10,20,0,0" Width="180"/> </StackPanel> </UserControl> |
vm Main
| 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 | public class MainViewModel : BindableBase { private string userAuth; public string UserAuth { get { return userAuth; } set { SetProperty(ref userAuth, value); } } private string userRole; public string UserRole { get { return userRole; } set { SetProperty(ref userRole, value); } } IEventAggregator _eventAggregator; private DelegateCommand _logoutcmd; public DelegateCommand LogoutCmd => _logoutcmd ?? (_logoutcmd = new DelegateCommand(ExecuteLogoutCommand)); private void ExecuteLogoutCommand() { bool loginState = false; if (_eventAggregator != null) _eventAggregator.GetEvent<LoginSentEvent>().Publish(loginState); } public MainViewModel(IEventAggregator aggregator) { _eventAggregator = aggregator; UserAuth = Thread.CurrentPrincipal.Identity.Name; UserRole = Thread.CurrentPrincipal.IsInRole("Admin")?"Администратор":"Пользователь"; } } |










