WPF Binding 用于数据有效性校验的关卡是它的 ValidationRules 属性,用于数据类型转换的关卡是它的 Converter 属性。下面是实例:

1. Binding 的数据校验

<Window x:Class="WpfStudy.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfStudy"
Title="MainWindow"
Height="266" Width="300">
<StackPanel>
<TextBox x:Name="textBox1" Margin="5"/>
<Slider x:Name="slider1" Minimum="0" Maximum="100" Margin="5"/>
</StackPanel>
</Window>
   public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent(); Binding binding = new Binding("Value") { Source = this.slider1 };
binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
binding.NotifyOnValidationError = true;
RangeValidationRule rvr = new RangeValidationRule();
rvr.ValidatesOnTargetUpdated = true;
binding.ValidationRules.Add(rvr);
this.textBox1.SetBinding(TextBox.TextProperty, binding); this.textBox1.AddHandler(Validation.ErrorEvent, new RoutedEventHandler(this.ValidationError));
} public void ValidationError(object sender, RoutedEventArgs e)
{
if (Validation.GetErrors(this.textBox1).Count > )
{
this.textBox1.ToolTip = Validation.GetErrors(this.textBox1)[].ErrorContent.ToString();
}
}
}
   public class RangeValidationRule : ValidationRule
{
//需要实现 Validate 方法
public override ValidationResult Validate(object value, CultureInfo cultureInfo)
{
double d = ;
if(double.TryParse(value.ToString(),out d))
{
if (d >= && d <= )
{
return new ValidationResult(true, null);
}
} return new ValidationResult(false, "Validation Failed");
}
}

完成后运行程序,当输入0到100之间的值时程序正常显示,但输入这个区间之外的值或不能被解析的值时 TextBox 会显示红色边框,表示值是错误的,不能把它传递给 Source。

 Binding 进行校验时的默认行为是认为来自 Source 的数据总是正确的,只有来自 Target 的数据(因为 Target 多为 UI 控件,所以等价于用户输入的数据)才有可能有问题,为了不让有问题的数据污染 Source 所以需要校验。换句话说,Binding 只在 Target 被外部方法更新时校验数据,而来自 Binding 的 Source 数据更新 Target 时是不会进行校验的。如果想改变这种行为,或者说当来自 Source 的数据也有可能出现问题时,我们就需要将校验的条件的 ValidateOnTargetUpdated 属性设为 true。

2. Binding 的数据转换

当数据从 Binding 的 Source 流向 Target 时,Convert 方法将被调用;反之,ConvertBack 方法将被调用。这两个方法的参数列表一模一样:第一个参数为 object,最大限度地保证了 Converter 的重用性(可以在方法体内对实际类型进行判断);第二个参数用于确定方法的返回类型(个人认为形参名字叫 outputType 比 targetType 要好,可以避免与 Binding  的 Target 混淆);第三个参数用于把额外的信息传入方法,若需要传递多个信息则可把信息放入一个集合对象来传入方法。

 Binding 对象的 Mode 属性会影响到这两个方法的调用。如果 Mode 为 TwoWay 或 Default 行为与 TwoWay 一致则两个方法都有可能被调用;如果 Mode 为 OneWay 或 Default 行为与 OneWay 一致则只有 Convert 方法会被调用;其他情况同理。

<Window x:Class="WpfStudy.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfStudy"
Title="MainWindow"
Height="266" Width="300">
<Window.Resources>
<local:CategoryToSourceConverter x:Key="cts"/>
<local:StateToNullableBoolConverter x:Key="stnb"/>
</Window.Resources>
<StackPanel Background="LightBlue">
<ListBox x:Name="listBoxPanel" Height="160" Margin="5">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Width="20" Height="20" Source="{Binding Path=Category,Converter={StaticResource cts}}"/>
<TextBlock Text="{Binding Path=Name}" Width="60" Margin="80,0"/>
<CheckBox IsThreeState="True" IsChecked="{Binding Path=State,Converter={StaticResource stnb}}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Button x:Name="buttonLoad" Content="Load" Height="25" Margin="5,0" Click="ButtonLoad_Click"/>
<Button x:Name="buttonSave" Content="Save" Height="25" Margin="5,5" Click="ButtonSave_Click"/>
</StackPanel>
</Window>
   public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
} private void ButtonLoad_Click(object sender, RoutedEventArgs e)
{
List<Plane> planeList = new List<Plane>()
{
new Plane() { Category = Category.Bomber, Name = "B-1", State = State.Unknown },
new Plane() { Category = Category.Bomber, Name = "B-2", State = State.Unknown },
new Plane() { Category = Category.Fighter, Name = "F-22", State = State.Unknown },
new Plane() { Category = Category.Fighter, Name = "Su-47", State = State.Unknown },
new Plane() { Category = Category.Bomber, Name = "B-52", State = State.Unknown },
new Plane() { Category = Category.Fighter, Name = "J-10", State = State.Unknown }
}; this.listBoxPanel.ItemsSource = planeList;
} private void ButtonSave_Click(object sender, RoutedEventArgs e)
{
StringBuilder sb = new StringBuilder();
foreach(Plane p in listBoxPanel.Items)
{
sb.AppendLine(string.Format("Category={0},Name={1},State={2}", p.Category, p.Name, p.State));
}
File.WriteAllText(@"D:\PlaneList.txt", sb.ToString());
}
}
    // Converters
public class CategoryToSourceConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo cultureinfo)
{
Category c = (Category)value;
switch (c)
{
case Category.Bomber:
return @"\Icons\Bomber.png";
case Category.Fighter:
return @"\Icons\Fighter.png";
default:
return null;
}
} public object ConvertBack(object value, Type targetType, object parameter, CultureInfo cultureinfo)
{
throw new NotImplementedException();
}
} public class StateToNullableBoolConverter : IValueConverter
{
// 将 State 转换为 bool?
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
State s = (State)value;
switch (s)
{
case State.Locked:
return false;
case State.Available:
return true;
case State.Unknown:
default:
return null;
}
} // 将 bool? 转换为 State
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
bool? nb = (bool?)value;
switch (nb)
{
case true:
return State.Available;
case false:
return State.Locked;
case null:
default:
return State.Unknown;
}
}
}
  //种类
public enum Category
{
Bomber,
Fighter
} //状态
public enum State
{
Available,
Locked,
Unknown
} //飞机
public class Plane
{
public Category Category { get; set; }
public string Name { get; set; }
public State State { get; set; }
}

3. MultiBinding(多路 Binding)

<Window x:Class="WpfStudy.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfStudy"
Title="MainWindow"
Height="266" Width="300">
<StackPanel Background="LightBlue">
<TextBox x:Name="textBox1" Height="23" Margin="5"/>
<TextBox x:Name="textBox2" Height="23" Margin="5,0"/>
<TextBox x:Name="textBox3" Height="23" Margin="5"/>
<TextBox x:Name="textBox4" Height="23" Margin="5,0"/>
<Button x:Name="button1" Content="Submit" Width="80" Margin="5"/>
</StackPanel>
</Window>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent(); this.SetMultiBinding();
} private void SetMultiBinding()
{
//准备基础Binding
Binding b1 = new Binding("Text") { Source = this.textBox1 };
Binding b2 = new Binding("Text") { Source = this.textBox2 };
Binding b3 = new Binding("Text") { Source = this.textBox3 };
Binding b4 = new Binding("Text") { Source = this.textBox4 }; //准备MultiBinding
MultiBinding mb = new MultiBinding() { Mode = BindingMode.OneWay };
mb.Bindings.Add(b1); //注意:MultiBinding对Add子Binding的顺序是敏感的
mb.Bindings.Add(b2);
mb.Bindings.Add(b3);
mb.Bindings.Add(b4);
mb.Converter = new LogonMultiBindingConverters(); //将 Button 与 MultiBinding 对象关联
this.button1.SetBinding(Button.IsEnabledProperty, mb);
}
}
public class LogonMultiBindingConverters : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if(!values.Cast<string>().Any(text=>string.IsNullOrEmpty(text))
&& values[].ToString() == values[].ToString()
&& values[].ToString() == values[].ToString())
{
return true;
}
return false;
} public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}

转自:《深入浅出 WPF》 第六章

WPF Converter(转)的更多相关文章

  1. WPF converter

    单值转换器 将单一值转换为特定类型的值,以日期转换为例如下: 1.定制DateConverter类,其中当值从绑定源传播给绑定目标时,调用方法Convert. 1 public class DateC ...

  2. WPF converter(包含传递复杂参数)

    单值转换器 将单一值转换为特定类型的值,以日期转换为例如下: 1.定制DateConverter类,其中当值从绑定源传播给绑定目标时,调用方法Convert. 1 public class DateC ...

  3. WPF Converter 使用复杂参数的方法

    Step 1在WPF的C#代码文件中给定义复杂类型的变量,并给其赋值:Sample code: List<User>lsUser=....Setp 2在 C#代码对应的XAML 中将此复杂 ...

  4. wpf converter converterparameter 绑定多参数

    1. converterparameter不是依赖属性,所以不能用binding. 2. 可以把converter 的接口 IValueConverter改为 IMultiValueConverter ...

  5. [WPF 容易忽视的细节] —— Exception in WPF's Converter

    前言: 在WPF中,Converter是我们经常要用到的一个工具,因为XAML上绑定的数据不一定是我们需要的数据. 问题: 在Converter中抛出一个异常导致程序崩溃,而且是在对未捕获异常进行集中 ...

  6. Silverlight或WPF动态绑定图片路径问题,不用Converter完美解决

    关于Silverlight或WPF动态绑定图片路径问题,不用Converter完美解决, 可想,一个固定的字符串MS都能找到,按常理动态绑定也应该没问题的,只需在前面标记它是一个Path类型的值它就能 ...

  7. WPF 之Converter

    WPF  之Converter Leo 在我们做项目的时候,经常会遇见这样的事情: 在数据中我们定义的是true,false 而在现实的时候则可能要求男,女 我们还得能定义成了0,1,2,3,4,5, ...

  8. 【WPF】wpf用MultiBinding解决Converter需要动态传参的问题,以Button为例

    原文:[WPF]wpf用MultiBinding解决Converter需要动态传参的问题,以Button为例       用Binding并通过Converter转换的时候,可能偶尔会遇到传参的问题, ...

  9. WPF的DataGrid的某个列绑定数据的三种方法(Binding、Converter、DataTrigger)

    最近在使用WPF的时候,遇到某个列的值需要根据内容不同进行转换显示的需求.尝试了一下,大概有三种方式可以实现: 1.传统的Binding方法,后台构造好数据,绑定就行. 2.转换器方法(Convert ...

随机推荐

  1. Codeforces 1150D(字符串dp)

    反思 三维的dp压根没看出来,看题解以后思路又很直观,找几道字符串dp练练才行 序列自动机和优化一维略 /* __ __ * ____| |_____| |____ * | | * | __ | * ...

  2. Leetcode572.Subtree of Another Tree另一个树的子树

    给定两个非空二叉树 s 和 t,检验 s 中是否包含和 t 具有相同结构和节点值的子树.s 的一个子树包括 s 的一个节点和这个节点的所有子孙.s 也可以看做它自身的一棵子树. 示例 1: 给定的树 ...

  3. pycharm最新激活码2017

    最新的2017激活码 BIG3CLIK6F-eyJsaWNlbnNlSWQiOiJCSUczQ0xJSzZGIiwibGljZW5zZWVOYW1lIjoibGFuIHl1IiwiYXNzaWduZW ...

  4. Django项目:CRM(客户关系管理系统)--06--03PerfectCRM创建基本数据01

    os.path.join(BASE_DIR, 'DBadd/DBadd_templates'), """ Django settings for PerfectCRM p ...

  5. Laravel 中 offset,limit 或 skip , take 的使用

    laravel 本身有一个自带的快速分页方法 paginate,只需要传入每页显示多少条数据就可以 了,但是如果想使用自定义从哪里开始呢. 一.offset,limit (offset 设置从哪里开始 ...

  6. C++ 实现十大排序算法

    教你手撕排序,这里有一个概念就是稳定排序.假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中,r[i]=r[j],且r[i]在r[j]之前, ...

  7. DirectX11笔记(十一)--Direct3D渲染7--RENDER STATES

    原文:DirectX11笔记(十一)--Direct3D渲染7--RENDER STATES 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/u010 ...

  8. Vue调试神器之Vue.js devTools

    Vue项目中使用Vue.js devTools这款调试神器,可以极大程度的提高我们的开发效率. 安装 1.打开Chrome网上应用商店安装插件(自墙),直接搜索devTools安装即可.贵宾传送阵,请 ...

  9. CSS浏览器兼容解决方案

    1.在ie8的甑别上,如何让样式只对ie8起作用? 用ie浏览器独有的文档注释的方式.像这样: <!DOCTYPE html> <!--> <html class=&qu ...

  10. linux下的OpenCV安装&学习笔记

    http://www.linuxdiyf.com/viewarticle.php?id=20731 (本想在fedora下安装编译的,但目前opencv官网.sourceforge等网站都无法访问下载 ...