WPF中MVMM开发模式实现数据验证
<Window x:Class="Validation.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:Validation"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<Style TargetType="TextBox">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="ToolTip" Value="{Binding RelativeSource={x:Static RelativeSource.Self},Path=(Validation.Errors)[0].ErrorContent}"/>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal" Grid.Row="0">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
<Label Content="First" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="30" />
<TextBox Text="{Binding Model.First,ValidatesOnDataErrors=True,UpdateSourceTrigger=PropertyChanged}"
Width="100" Height="40" Background="AliceBlue" HorizontalContentAlignment="Left" FontWeight="Bold" VerticalContentAlignment="Center" FontSize="15"/>
</StackPanel>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<Label Content="Second" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="30"/>
<TextBox Text="{Binding Model.Second,ValidatesOnDataErrors=True,UpdateSourceTrigger=PropertyChanged}"
Width="100" Height="40" Background="AliceBlue" HorizontalContentAlignment="Left" VerticalContentAlignment="Center" FontWeight="Bold" VerticalAlignment="Center" FontSize="15"/>
</StackPanel>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<Label Content="Result" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="30"/>
<TextBox Text="{Binding Model.Result,ValidatesOnDataErrors=True,UpdateSourceTrigger=PropertyChanged}"
Width="100" Height="40" Background="AliceBlue" HorizontalContentAlignment="Left" FontWeight="Bold" VerticalContentAlignment="Center" FontSize="15" />
</StackPanel>
</StackPanel>
<Button Content="Add" Width="100" Height="50" Grid.Row="1" FontSize="30" Command="{Binding Add}"/>
</Grid>
</Window>
业务逻辑
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 Validation
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new ViewModel();
}
}
public class ViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public ICommand Add { get; private set; }
public Model Model { get; set; }
public ViewModel()
{
Add = new RelayCommand(OnAdd, CanAdd);
Model = new Model();
}
private void OnAdd(object obj)
{
Model.Result = (Convert.ToInt32(Model.First) + Convert.ToInt32(Model.Second)).ToString();
}
private bool CanAdd(object arg)
{
//return !string.IsNullOrEmpty(Model.First) && !string.IsNullOrEmpty(Model.Second)
// && Int32.TryParse(Model.First, out var first) && Int32.TryParse(Model.Second, out var second);
return true;
}
}
public class Model : INotifyPropertyChanged, IDataErrorInfo
{
private string _first;
public string First
{
get { return _first; }
set
{
_first = value;
PropertyChanged.Invoke(this, new PropertyChangedEventArgs(nameof(First)));
}
}
private string _second;
public string Second
{
get { return _second; }
set
{
_second = value;
PropertyChanged.Invoke(this, new PropertyChangedEventArgs(nameof(Second)));
}
}
private string _result;
public string Result
{
get { return _result; }
set
{
_result = value;
PropertyChanged.Invoke(this, new PropertyChangedEventArgs(nameof(Result)));
}
}
public string this[string propertyName]
{
get
{
if ((!Int32.TryParse(First, out var first) && !string.IsNullOrEmpty(First)) || (!Int32.TryParse(Second, out var second) && !string.IsNullOrEmpty(Second)))
{
return "Only Integer";
}
else
{
return string.Empty;
}
}
}
public string Error => string.Empty;
public event PropertyChangedEventHandler PropertyChanged;
}
public class RelayCommand : ICommand
{
Action<object> _action;
Func<object, bool> _func;
public RelayCommand(Action<object> action, Func<object, bool> func)
{
_action = action;
_func = func;
}
public RelayCommand(Action<object> action)
{
_action = action;
}
public event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter)
{
var result = _func.Invoke(parameter);
return result;
}
public void Execute(object parameter)
{
_action.Invoke(parameter);
}
}
}
效果: