背景
MVVM 是一种软件架构模式,用于创建用户界面。它将用户界面(View)、业务逻辑(ViewModel)和数据模型(Model)分离开来,以提高代码的可维护性和可测试性。
MainWindow 类是 View(视图),负责用户界面的呈现和交互,它是用户直接看到和操作的部分。
LoginVM 类是 ViewModel(视图模型),它充当了 View 和 Model 之间的中介,处理了视图与数据模型之间的交互逻辑,以及用户操作的响应逻辑。
LoginModel 类是 Model(模型),它包含了应用程序的数据和业务逻辑,用于存储和处理用户的身份验证信息。
展示
代码
LoginModel.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WpfApp2
{
public class LoginModel
{
private string _UserName;
public string UserName
{
get { return _UserName; }
set
{
_UserName = value;
}
}
private string _Password;
public string Password
{
get { return _Password; }
set
{
_Password = value;
}
}
}
}
LoginVM.cs
using Sys tem;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
namespace WpfApp2
{
public class LoginVM : INotifyPropertyChanged
{
private MainWindow _main;
public LoginVM(MainWindow main)
{
_main = main;
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropetyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
private LoginModel _LoginM = new LoginModel();
public string UserName
{
get { return _LoginM.UserName; }
set
{
_LoginM.UserName = value;
RaisePropetyChanged("UserName");
}
}
public string Password
{
get { return _LoginM.Password; }
set
{
_LoginM.Password = value;
RaisePropetyChanged("Password");
}
}
/// <summary>
/// 登录方法
/// </summary>
void Loginfunc()
{
if (UserName == "wpf" && Password == "666")
{
MessageBox.Show("OK");
Index index = new Index();
index.Show();
//想办法拿到mainwindow
_main.Hide();
}
else
{
MessageBox.Show("输入的用户名或密码不正确");
UserName = "";
Password = "";
}
}
bool CanLoginExecute()
{
return true;
}
public ICommand LoginAction
{
get
{
return new RelayCommand(Loginfunc,CanLoginExecute);
}
}
}
}
MainWindow.xaml
<Window x:Class="WpfApp2.MainWindow"
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:WpfApp2"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto"></RowDefinition>
<RowDefinition Height="auto"></RowDefinition>
<RowDefinition Height="1*"></RowDefinition>
<RowDefinition Height="9*"></RowDefinition>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Text="上海市-市图书馆" FontSize="18" HorizontalAlignment="Center"></TextBlock>
<StackPanel Grid.Row="1" Grid.Column="0" Background="#0078d4">
<TextBlock Text="登录" FontSize="22" HorizontalAlignment="Center" Foreground="Wheat" Margin="5">
</TextBlock>
</StackPanel>
<Grid Grid.Row="3" ShowGridLines="False" HorizontalAlignment="Center">
<Grid.RowDefinitions>
<RowDefinition Height="30"></RowDefinition>
<RowDefinition Height="30"></RowDefinition>
<RowDefinition Height="30"></RowDefinition>
<RowDefinition Height="30"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions >
<ColumnDefinition Width="auto"></ColumnDefinition>
<ColumnDefinition Width="200"></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBlock Text="用户名" Grid.Row="0" Grid.Column="0" VerticalAlignment="Center"></TextBlock>
<TextBox Text="{Binding UserName}" Grid.Row="0" Grid.Column="1" Margin="2" ></TextBox>
<TextBlock Text="密码" Grid.Row="1" Grid.Column="0" VerticalAlignment="Center"></TextBlock>
<TextBox Text="{Binding Password}" Grid.Row="1" Grid.Column="1" Margin="2"></TextBox>
<CheckBox Grid.ColumnSpan="2" Content="记住密码" Grid.Row="2"></CheckBox>
<local:CustomButton ButtonCornerRadius="5" BackgroundHover="Red" BackgroundPressed="Green" Foreground="#FFFFFF" Background="#3C7FF8" Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2" Command="{Binding LoginAction}" Height="30" VerticalAlignment="Top">登录</local:CustomButton>
</Grid>
</Grid>
</Window>
MainWindow.xaml.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WpfApp2
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
LoginVM loginVM;
public MainWindow()
{
InitializeComponent();
loginVM = new LoginVM(this);
this.DataContext = loginVM;
}
}
}
RelayCommand.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
namespace WpfApp2
{
public class RelayCommand : ICommand
{
/// <summary>
/// 命令是否能够执行
/// </summary>
readonly Func<bool> _canExecute;
/// <summary>
/// 命令需要执行的方法
/// </summary>
readonly Action _exexute;
public RelayCommand(Action exexute,Func<bool> canExecute)
{
_canExecute = canExecute;
_exexute = exexute;
}
public bool CanExecute(object parameter)
{
if (_canExecute == null)
{
return true;
}
return _canExecute();
}
public void Execute(object parameter)
{
_exexute();
}
public event EventHandler CanExecuteChanged
{
add {
if (_canExecute != null)
{
CommandManager.RequerySuggested += value;
}
}
remove
{
if (_canExecute != null)
{
CommandManager.RequerySuggested -= value;
}
}
}
}
}
自定义按钮CustomButton
App.xaml.cs
<Application x:Class="WpfApp2.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApp2"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="CustomButtonStyles.xaml"></ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
CustomButton.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace WpfApp2
{
public class CustomButton:Button
{
//依赖属性
public CornerRadius ButtonCornerRadius
{
get { return (CornerRadius)GetValue(ButtonCornerRadiusProperty); }
set { SetValue(ButtonCornerRadiusProperty, value); }
}
// Using a DependencyProperty as the backing store for ButtonCornerRadius. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ButtonCornerRadiusProperty =
DependencyProperty.Register("ButtonCornerRadius", typeof(CornerRadius), typeof(CustomButton));
public Brush BackgroundHover
{
get { return (Brush)GetValue(BackgroundHoverProperty); }
set { SetValue(BackgroundHoverProperty, value); }
}
// Using a DependencyProperty as the backing store for BackgroundHover. This enables animation, styling, binding, etc...
public static readonly DependencyProperty BackgroundHoverProperty =
DependencyProperty.Register("BackgroundHover", typeof(Brush), typeof(CustomButton));
public Brush BackgroundPressed
{
get { return (Brush)GetValue(BackgroundPressedProperty); }
set { SetValue(BackgroundPressedProperty, value); }
}
// Using a DependencyProperty as the backing store for BackgroundPressed. This enables animation, styling, binding, etc...
public static readonly DependencyProperty BackgroundPressedProperty =
DependencyProperty.Register("BackgroundPressed", typeof(Brush), typeof(CustomButton));
}
}
数据字典
CustombuttonStyles.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:bb="clr-namespace:WpfApp2">
<Style TargetType="{x:Type bb:CustomButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type bb:CustomButton}">
<Border x:Name="buttonBorder" Background="{TemplateBinding Background}" CornerRadius="{TemplateBinding ButtonCornerRadius}">
<TextBlock Text="{TemplateBinding Content}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"></TextBlock>
</Border>
<!--触发器-->
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="buttonBorder" Property="Background" Value="{Binding BackgroundHover,RelativeSource={RelativeSource TemplatedParent}}"></Setter>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="buttonBorder" Property="Background" Value="{Binding BackgroundPressed,RelativeSource={RelativeSource TemplatedParent}}"></Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>