由于Binding只把Convert成功的值送往Source,当目标中的值Convert失败时Source的值依然是旧值,所以ViewModel必须获取View的输入验证状态,以下是本人的实现。

当“+”号两边输入正确时,“Add”可用,当所有“+”号两边输入正确时,“Add All”可用。

通过Behavior添加Validation.ErrorEvent路由事件的事件处理器,在该事件处理器中把HasError状态写入自定义的附加属性,附加属性可以绑定。

Behavior派生类引用System.Windows.Interactivity.dll,代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Interactivity; namespace Calculater
{
public class NotifyErrorBehavior : Behavior<UIElement>
{
protected override void OnAttached()
{
base.OnAttached(); this.AssociatedObject.AddHandler(Validation.ErrorEvent, new RoutedEventHandler(HasErrorChanged));
} protected override void OnDetaching()
{
base.OnDetaching();
this.AssociatedObject.RemoveHandler(Validation.ErrorEvent, new RoutedEventHandler(HasErrorChanged));
} private static void HasErrorChanged(object sender, RoutedEventArgs e)
{
DependencyObject d = e.OriginalSource as DependencyObject;
HasErrorHelper.SetHasError(d, Validation.GetHasError(d));
}
}
}

附加属性代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls; namespace Calculater
{
public class HasErrorHelper
{
public static bool GetHasError(DependencyObject obj)
{
return (bool)obj.GetValue(HasErrorProperty);
} public static void SetHasError(DependencyObject obj, bool value)
{
obj.SetValue(HasErrorProperty, value);
} public static readonly DependencyProperty HasErrorProperty =
DependencyProperty.RegisterAttached("HasError", typeof(bool), typeof(HasErrorHelper), new PropertyMetadata(false));
}
}

View代码:

<UserControl x:Class="Calculater.ChildCalculater"
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:Calculater"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
mc:Ignorable="d"
d:DesignHeight="" d:DesignWidth="">
<i:Interaction.Behaviors>
<local:NotifyErrorBehavior></local:NotifyErrorBehavior>
</i:Interaction.Behaviors>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="Auto"/>
<ColumnDefinition />
<ColumnDefinition Width="Auto"/>
<ColumnDefinition />
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBox Margin="" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" local:HasErrorHelper.HasError="{Binding Path=HasErrorX,Mode=OneWayToSource}">
<Binding Path="X" NotifyOnValidationError="True" UpdateSourceTrigger="PropertyChanged" TargetNullValue="" />
</TextBox>
<Label Margin="" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" Grid.Column="">+</Label>
<TextBox Margin="" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Grid.Column="" local:HasErrorHelper.HasError="{Binding Path=HasErrorY,Mode=OneWayToSource}">
<Binding Path="Y" NotifyOnValidationError="True" UpdateSourceTrigger="PropertyChanged" TargetNullValue="" />
</TextBox>
<Label Margin="" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" Grid.Column="">=</Label>
<TextBox Margin="" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Grid.Column="" IsReadOnly="True">
<Binding Path="Sum" TargetNullValue="" />
</TextBox>
<Button Margin="" Grid.Column="" Padding="" Command="{Binding CalculateCommand}">Add</Button>
<Button Margin="" Grid.Column="" Padding="" Command="{Binding ResetCommand}">Reset</Button>
</Grid>
</UserControl>

ViewModel引用Microsoft.Practices.Prism.dll,代码如下:

using Microsoft.Practices.Prism.Commands;
using Microsoft.Practices.Prism.ViewModel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace Calculater
{
class ChildCalculaterViewModel : NotificationObject
{
public ChildCalculaterViewModel()
{
this._calculateCommand = new DelegateCommand(this.Calculate, this.CanCalculate);
this._resetCommand = new DelegateCommand(this.Reset); CalculaterCommand.CalculateAllCommand.RegisterCommand(this.CalculateCommand);
CalculaterCommand.ResetAllCommand.RegisterCommand(this.ResetCommand); } private double? _x; public double? X
{
get { return _x; }
set
{
if (_x != value)
{
_x = value;
this.RaisePropertyChanged("X");
this.Sum = null;
this.CalculateCommand.RaiseCanExecuteChanged();
} }
} private double? _y; public double? Y
{
get { return _y; }
set
{
if (_y != value)
{
_y = value;
this.RaisePropertyChanged("Y");
this.Sum = null;
this.CalculateCommand.RaiseCanExecuteChanged();
} }
} private double? _sum; public double? Sum
{
get { return _sum; }
set
{
if (_sum != value)
{
_sum = value;
this.RaisePropertyChanged("Sum");
} }
} private bool _hasErrorX; public bool HasErrorX
{
get { return _hasErrorX; }
set
{
if (_hasErrorX != value)
{
_hasErrorX = value;
this.Sum = null;
this.CalculateCommand.RaiseCanExecuteChanged();
} }
} private bool _hasErrorY; public bool HasErrorY
{
get { return _hasErrorY; }
set
{
if (_hasErrorY != value)
{
_hasErrorY = value;
this.Sum = null;
this.CalculateCommand.RaiseCanExecuteChanged();
} }
} private DelegateCommand _calculateCommand; public DelegateCommand CalculateCommand
{
get { return _calculateCommand; }
} private bool CanCalculate()
{
if (this.HasErrorX || this.HasErrorY || !this.X.HasValue || !this.Y.HasValue)
{
return false;
} return true;
} private void Calculate()
{
try
{
double x = this.X.Value;
double y = this.Y.Value; this.Sum = x + y;
}
catch
{
return;
}
} private DelegateCommand _resetCommand; public DelegateCommand ResetCommand
{
get { return _resetCommand; }
} private void Reset()
{
this.X = null;
this.Y = null;
this.Sum = null;
}
}
}

主窗体代码:

<Window x:Class="Calculater.Shell"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Calculater"
xmlns:prism="http://www.codeplex.com/prism"
Title="Calculater" Height="" Width="">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition />
</Grid.RowDefinitions>
<local:ChildCalculater></local:ChildCalculater>
<local:ChildCalculater Grid.Row=""></local:ChildCalculater>
<local:ChildCalculater Grid.Row=""></local:ChildCalculater>
<Grid Grid.Row="">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Button Margin="" HorizontalAlignment="Right" Padding="" Content="Add All" Command="{x:Static local:CalculaterCommand.CalculateAllCommand}"></Button>
<Button Margin="" HorizontalAlignment="Left" Padding="" Grid.Column="" Content="Reset All" Command="{x:Static local:CalculaterCommand.ResetAllCommand}"></Button>
</Grid>
</Grid>
</Window>
using Microsoft.Practices.Prism.Commands;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace Calculater
{
public static class CalculaterCommand
{
private static CompositeCommand _calculateAllCommand = new CompositeCommand(); public static CompositeCommand CalculateAllCommand
{
get { return _calculateAllCommand; }
} private static CompositeCommand _resetAllCommand = new CompositeCommand(); public static CompositeCommand ResetAllCommand
{
get { return _resetAllCommand; }
} }
}

MVVM实现ViewModel获取View输入验证状态的更多相关文章

  1. [WPF] 在 ViewModel 中让数据验证出错(Validation.HasError)的控件获得焦点

    1. 需求 在 MVVM 中 ViewModel 和 View 之间的交互通常都是靠 Icommand 和 INotifyPropertyChanged,不过有时候还会需要从 MVVM 中控制 Vie ...

  2. MVVM模式下,ViewModel和View,Model有什么区别

    摘自正美的5群 Model:很简单,就是业务逻辑相关的数据对象,通常从数据库映射而来,我们可以说是与数据库对应的model. View:也很简单,就是展现出来的用户界面. 基本上,绝大多数软件所做的工 ...

  3. js架构设计模式——MVVM模式下,ViewModel和View,Model有什么区别

    MVVM模式下,ViewModel和View,Model有什么区别 Model:很简单,就是业务逻辑相关的数据对象,通常从数据库映射而来,我们可以说是与数据库对应的model. View:也很简单,就 ...

  4. MVVM模式中ViewModel和View、Model有什么区别

    Model:很简单,就是业务逻辑相关的数据对象,通常从数据库映射而来,我们可以说是与数据库对应的model. View:也很简单,就是展现出来的用户界面. 基本上,绝大多数软件所做的工作无非就是从数据 ...

  5. WPF MVVM(Caliburn.Micro) 数据验证

    书接前文 前文中仅是WPF验证中的一种,我们暂且称之为View端的验证(因为其验证规是写在Xaml文件中的). 还有一种我们称之为Model端验证,Model通过继承IDataErrorInfo接口来 ...

  6. 获取view宽高

    在oncreate()中利用view.getWidth()或是view.getHeiht()来获取view的宽和高,看似没有问题,其实他们去得值是0,并不是你想要的结果? 这是为什么呢? 在调用onc ...

  7. [Swift通天遁地]二、表格表单-(8)快速实现表单的输入验证

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...

  8. silverlight wpf Command提交时输入验证

    silverlight 或WPF在MVVM模式中使用INotifyDataErrorInfo接口对输入进行验证时 控件lostFocus时会触发验证,但在提交动作(例如button的Command)时 ...

  9. Struts2的输入验证

    一.概述: ① Struts2的输入验证 –基于 XWorkValidation Framework的声明式验证:Struts2提供了一些基于 XWork Validation Framework的内 ...

随机推荐

  1. openstack——nova计算服务

    一.nova介绍               Nova 是 OpenStack 最核心的服务,负责维护和管理云环境的计算资源.OpenStack 作为 IaaS 的云操作系统,虚拟机生命周期管理也就是 ...

  2. 【css】最近使用的两种图标字体库

    ## 0. 前言 比较基础的图标加载:<img src="x.png">和块元素的背景background: url(./x.png). 页面多图标时,使用雪碧图(多个 ...

  3. [数据结构】【c语言】链表的创建和遍历

    第一次写代码的博客,一个刚刚接触的新手,来这里主要是为了记录自己,方便自己以后浏览,也欢迎大家指正.先来个简单的,动态链表的创建和遍历. #include<stdio.h> #includ ...

  4. mysql-索引、导入、导出、备份、恢复

    1.索引 索引是一种与表有关的结构,它的作用相当于书的目录,可以根据目录中的页码快速找到所需的内容. 当表中有大量记录时,若要对表进行查询,没有索引的情况是全表搜索:将所有记录一一取出,和查询条件进行 ...

  5. 洛谷 P2827 BZOJ 4721 UOJ #264 蚯蚓

    题目描述 本题中,我们将用符号表示对c向下取整,例如:. 蛐蛐国最近蚯蚓成灾了!隔壁跳蚤国的跳蚤也拿蚯蚓们没办法,蛐蛐国王只好去请神刀手来帮他们消灭蚯蚓. 蛐蛐国里现在共有n只蚯蚓(n为正整数).每只 ...

  6. POJ - 3541 - Given a string…

    Given a string… Time Limit: 10000MS   Memory Limit: 65536K Total Submissions: 1819   Accepted: 390 C ...

  7. noip2013 Day2 T2 花匠 解题报告

    题目: 3289 花匠 2013年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目描述 Description 花匠栋栋种了一排花,每株花都有自己的高度.花儿越长越大, ...

  8. P1464 Function 洛谷

    https://www.luogu.org/problem/show?pid=1464 题目描述 对于一个递归函数w(a,b,c) 如果a<=0 or b<=0 or c<=0就返回 ...

  9. 洛谷——P2676 超级书架

    https://www.luogu.org/problem/show?pid=2676#sub 题目描述 Farmer John最近为奶牛们的图书馆添置了一个巨大的书架,尽管它是如此的大,但它还是几乎 ...

  10. code vs 3376 符号三角形

    3376 符号三角形  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold 题解       题目描述 Description 如下图是由14个“+”和14个“-”组 ...