2021-09-02 WPF上位机通用框架平台实战-登录窗口

Posted 微软MVP Eleven

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021-09-02 WPF上位机通用框架平台实战-登录窗口相关的知识,希望对你有一定的参考价值。

一:登录窗口布局和功能实现

<Window x:Class="Zhaoxi.HostComputer.Views.LoginWindow"
        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:local="clr-namespace:Zhaoxi.HostComputer.Views"
        xmlns:vm="clr-namespace:Zhaoxi.HostComputer.ViewModels"
        xmlns:base="clr-namespace:Zhaoxi.HostComputer.Base"
        mc:Ignorable="d"
        Background="Transparent" FontFamily="Microsoft YaHei" FontWeight="ExtraLight" ResizeMode="NoResize"
        WindowStyle="None" AllowsTransparency="True" WindowStartupLocation="CenterScreen"
        SizeToContent="WidthAndHeight"
        Title="LoginWindow">
    <Window.Resources>
        <ControlTemplate TargetType="Button" x:Key="CloseButtonTemplate">
            <Grid Background="Transparent" Name="back">
                <TextBlock Text="&#xe653;" 
                           FontFamily="{DynamicResource iconfont}" VerticalAlignment="Center" HorizontalAlignment="Center"
                           FontSize="14"/>
            </Grid>
            <ControlTemplate.Triggers>
                <Trigger Property="IsMouseOver" Value="True">
                    <Setter Property="Background" Value="#DDD" TargetName="back"/>
                </Trigger>
            </ControlTemplate.Triggers>
        </ControlTemplate>

        <Style TargetType="TextBox" x:Key="UsernameTextBoxStyle">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type TextBox}">
                        <Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" 
                                    BorderThickness="{TemplateBinding BorderThickness}" 
                                    Background="{TemplateBinding Background}" 
                                    SnapsToDevicePixels="True"
                                    CornerRadius="5">
                            <Grid>
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="40"/>
                                    <ColumnDefinition/>
                                </Grid.ColumnDefinitions>
                                <Border BorderBrush="#DDD" BorderThickness="0,0,1,0" Margin="0,8,5,8"/>
                                <TextBlock Text="请输入用户名" Grid.Column="1" VerticalAlignment="Center" Foreground="#BBB"
                               Name="markText" Visibility="Collapsed" FontSize="12" Margin="2,0"/>
                                <TextBlock Text="&#xe610;"
                                           FontFamily="{DynamicResource iconfont}" FontSize="14" VerticalAlignment="Center" HorizontalAlignment="Center"
                                           Foreground="#DDD"/>
                                <ScrollViewer x:Name="PART_ContentHost" Focusable="false"
                                                  HorizontalScrollBarVisibility="Hidden" 
                                                  VerticalScrollBarVisibility="Hidden"
                                                  Grid.Column="1"
                                                  VerticalAlignment="Center" MinHeight="20"/>
                            </Grid>
                        </Border>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsEnabled" Value="false">
                                <Setter Property="Opacity" TargetName="border" Value="0.56"/>
                            </Trigger>
                            <Trigger Property="IsMouseOver" Value="true">
                                <Setter Property="BorderBrush" TargetName="border" Value="#FF7EB4EA"/>
                            </Trigger>
                            <Trigger Property="IsKeyboardFocused" Value="true">
                                <Setter Property="BorderBrush" TargetName="border" Value="#FF569DE5"/>
                            </Trigger>
                            <DataTrigger Binding="{Binding Path=Text,RelativeSource={RelativeSource Mode=Self}}" Value="">
                                <Setter Property="Visibility" TargetName="markText" Value="Visible"/>
                            </DataTrigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

        <Style x:Key="PasswordBoxStyle" TargetType="{x:Type PasswordBox}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type PasswordBox}">
                        <Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" 
                                    BorderThickness="{TemplateBinding BorderThickness}" 
                                    Background="{TemplateBinding Background}" 
                                    SnapsToDevicePixels="True"
                                    CornerRadius="5">
                            <Grid>
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="40"/>
                                    <ColumnDefinition/>
                                </Grid.ColumnDefinitions>
                                <Border BorderBrush="#DDD" BorderThickness="0,0,1,0" Margin="0,8,5,8"/>
                                <TextBlock Text="请输入密码" Grid.Column="1" VerticalAlignment="Center" Foreground="#BBB"
                                           Name="markText" Visibility="Collapsed" FontSize="12" Margin="2,0"/>
                                <TextBlock Text="&#xe602;" FontFamily="{StaticResource iconfont}" FontSize="14" VerticalAlignment="Center" HorizontalAlignment="Center"
                                               Foreground="#DDD"/>
                                <ScrollViewer x:Name="PART_ContentHost" Focusable="false"
                                                  HorizontalScrollBarVisibility="Hidden" 
                                                  VerticalScrollBarVisibility="Hidden"
                                                  Grid.Column="1"
                                                  VerticalAlignment="Center" MinHeight="20"/>
                            </Grid>
                        </Border>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsEnabled" Value="false">
                                <Setter Property="Opacity" TargetName="border" Value="0.56"/>
                            </Trigger>
                            <Trigger Property="IsMouseOver" Value="true">
                                <Setter Property="BorderBrush" TargetName="border" Value="#FF7EB4EA"/>
                            </Trigger>
                            <Trigger Property="IsKeyboardFocused" Value="true">
                                <Setter Property="BorderBrush" TargetName="border" Value="#FF569DE5"/>
                            </Trigger>
                            <DataTrigger Binding="{Binding Path=UserModel.Password}" Value="">
                                <Setter Property="Visibility" TargetName="markText" Value="Visible"/>
                            </DataTrigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            <Style.Triggers>
                <MultiTrigger>
                    <MultiTrigger.Conditions>
                        <Condition Property="IsInactiveSelectionHighlightEnabled" Value="true"/>
                        <Condition Property="IsSelectionActive" Value="false"/>
                    </MultiTrigger.Conditions>
                    <Setter Property="SelectionBrush" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightBrushKey}}"/>
                </MultiTrigger>
            </Style.Triggers>
        </Style>

    </Window.Resources>
    <Window.Triggers>
        <EventTrigger RoutedEvent="Window.Loaded">
            <BeginStoryboard>
                <Storyboard>
                    <DoubleAnimation Duration="0:0:0.5" To="0" 
                                     Storyboard.TargetName="tt"
                                     Storyboard.TargetProperty="X"/>
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </Window.Triggers>

    <Grid Width="740" Margin="5" Background="Transparent" MouseLeftButtonDown="Grid_MouseLeftButtonDown">
        <Border Background="#F7F9FA" Margin="0,6" HorizontalAlignment="Right" Width="330" BorderBrush="#DDD" BorderThickness="0"
                CornerRadius="0,5,5,0">
            <Border.Effect>
                <DropShadowEffect Color="Black" ShadowDepth="0" Direction="0" BlurRadius="10" Opacity="0.2"/>
            </Border.Effect>
            <Border.RenderTransform>
                <TranslateTransform X="-350" x:Name="tt"/>
            </Border.RenderTransform>
            <Grid HorizontalAlignment="Right" Width="230" Margin="30,30,30,10">
                <Grid.RowDefinitions>
                    <RowDefinition Height="100"/>
                    <RowDefinition/>
                    <RowDefinition/>
                    <RowDefinition/>
                    <RowDefinition Height="60"/>
                    <RowDefinition Height="auto" MinHeight="40"/>
                </Grid.RowDefinitions>
                <StackPanel VerticalAlignment="Center" Margin="0,0,0,30">
                    <TextBlock Text="智控平台" Foreground="#333" FontSize="22"/>
                    <TextBlock Text="专注于提升工业智能管理协作平台" FontSize="12" Foreground="#888" Margin="0,10,0,0"/>
                </StackPanel>

                <TextBox Grid.Row="1" Height="35" Margin="0,8" Style="{StaticResource UsernameTextBoxStyle}"
                         VerticalContentAlignment="Center" FontSize="14"
                         Text="{Binding UserModel.UserName,UpdateSourceTrigger=PropertyChanged}"/>
                <PasswordBox Grid.Row="2" Height="35" Margin="0,8" Style="{StaticResource PasswordBoxStyle}"
                             base:PasswordBoxHelper.Attach="true"
                             base:PasswordBoxHelper.Password="{Binding UserModel.Password,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
                             FontSize="14"/>
                <CheckBox Grid.Row="3" Content="记住登录信息" VerticalAlignment="Center" FontSize="10" VerticalContentAlignment="Center"/>
                <TextBlock Grid.Row="3" HorizontalAlignment="Right" VerticalAlignment="Center">
                    <Hyperlink>忘记密码</Hyperlink>
                </TextBlock>

                <Button Content="登    录" Background="#FF104991" Foreground="White" Grid.Row="4" Height="30" Margin="0,8" BorderThickness="0" VerticalAlignment="Top"
                        Command="{Binding LoginCommand}" CommandParameter="{Binding Path=.,RelativeSource={RelativeSource AncestorType=Window}}"/>

                <Button VerticalAlignment="Top" HorizontalAlignment="Right" Content="X" Margin="0,-30,-25,0"
                        Template="{StaticResource CloseButtonTemplate}" Width="40" Height="30"
                        Command="{Binding CloseCommand}" CommandParameter="{Binding Path=.,RelativeSource={RelativeSource AncestorType=Window}}"/>

                <TextBlock Text="{Binding ErrorMsg}" Foreground="Red" TextWrapping="Wrap" Grid.Row="10"
                           TextAlignment="Center"/>
            </Grid>
        </Border>

        <Polygon Points="0 0,420,0,450 200 420 400 0 400" StrokeThickness="0" Stroke="White" HorizontalAlignment="Left">
            <Polygon.Fill>
                <ImageBrush ImageSource="pack://application:,,,/Zhaoxi.HostComputer;component/Assets/Images/login_image.jpg" Stretch="UniformToFill" Viewbox="0,0,1.4,1">
                    
                </ImageBrush>
            </Polygon.Fill>
            <Polygon.Effect>
                <DropShadowEffect Color="Black" ShadowDepth="0" Direction="0" BlurRadius="10" Opacity="0.3"/>
            </Polygon.Effect>
        </Polygon>
        <Polygon Points="0 0,420,0,450 200 420 400 0 400" Opacity="0.2" StrokeThickness="0" Stroke="White" HorizontalAlignment="Left">
            <Polygon.Fill>
                <RadialGradientBrush>
                    <GradientStop Color="#22FFFFFF" Offset="0"/>
                    <GradientStop Color="#FF1B283C" Offset="1"/>
                    <GradientStop Color="#C6555F6E" Offset="0.617"/>
                </RadialGradientBrush>
            </Polygon.Fill>
        </Polygon>
    </Grid>
</Window>
/// <summary>
/// LoginWindow.xaml 的交互逻辑
/// </summary>
public partial class LoginWindow : Window
{
    public LoginWindow()
    {
        InitializeComponent();
        this.DataContext = new LoginViewModel();
    }

    private void Grid_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        this.DragMove();
    }
}
public class UserModel : NotifyBase
{
    private string _userName;

    public string UserName
    {
        get { return _userName; }
        set { _userName = value; this.NotifyChanged(); }
    }

    private string _password = "";

    public string Password
    {
        get { return _password; }
        set { _password = value; this.NotifyChanged(); }
    }

    public string RealName { get; set; }
    public string Avatar { get; set; }
}
public class LoginViewModel : NotifyBase
{
    LoginService loginService = new LoginService();

    public UserModel UserModel { get; set; } = new UserModel();

    private string _errorMsg;

    public string ErrorMsg
    {
        get { return _errorMsg; }
        set { _errorMsg = value; this.NotifyChanged(); }
    }


    private CommandBase _closeCommand;

    public CommandBase CloseCommand
    {
        get
        {
            if (_closeCommand == null)
            {
                _closeCommand = new CommandBase();
                _closeCommand.DoExecute = new Action<object>(obj =>
                {
                    (obj as System.Windows.Window).DialogResult = false;
                });
            }
            return _closeCommand;
        }
    }


    private CommandBase _loginCommand;

    public CommandBase LoginCommand
    {
        get
        {
            if (_loginCommand == null)
            {
                _loginCommand = new CommandBase();
                _loginCommand.DoExecute = new Action<object>(obj =>
                {
                    this.ErrorMsg = "";
                    try
                    {
                        if (loginService.CheckLogin(UserModel.UserName, UserModel.Password))
                            (obj as System.Windows.Window).DialogResult = true;
                    }
                    catch (Exception ex)
                    {
                        this.ErrorMsg = ex.Message;
                    }
                });
            }
            return _loginCommand;
        }
    }
}

事件触发功能封装

public class CommandBase : ICommand
{
    public event EventHandler CanExecuteChanged;

    public bool CanExecute(object parameter)
    {
        return true;
    }

    public void Execute(object parameter)
    {
        DoExecute?.Invoke(parameter);
    }

    public Action<object> DoExecute { get; set; }
}

双向绑定功能封装

public class Notif

以上是关于2021-09-02 WPF上位机通用框架平台实战-登录窗口的主要内容,如果未能解决你的问题,请参考以下文章

2021-09-04 WPF上位机通用框架平台实战-设备编辑

2021-09-04 WPF上位机通用框架平台实战-全局监控对象

2021-09-03 WPF上位机通用框架平台实战-Dashboard

2021-09-04 WPF上位机通用框架平台实战-Device

2021-09-04 WPF上位机通用框架平台实战-主窗口

有小伙伴问:上位机用QT还是winform/wpf好?