Binding的数据转换与校验(WPF)
2011-12-15 23:30 木木子 阅读(625) 评论(0) 编辑 收藏 举报大概
- 一些闲话
- Binding对数据转换
- Binding对数据校验
闲话
离上次做完Binding基础的笔记有段日子了。主要天气冷了,人的惰性就起作用了,打字真是手冷啊。但,这样懒下去也不是办法,男人就是要对自己狠点。就今晚了,一把鼻涕一把热茶地把Binding的剩余部分回顾下,把笔记也做了,fighting……
Binding的数据校验
Binding的Validation属性类型是Collection<ValidationRule>,即可以为一个Binding设置多个Validation条件。Validation类是一个抽象类,使用时需要创建派生类,并且实现它的Validation方法。Validation方法返回ValidationResult类型对象。ValidationResult构造函数需要传入两个参数,分别为Boolean型isValid: true表示校验通过;反之false。还有一个为Object型errorContent。
Binding默认是校验来自Target的数据,加入需要校验Source的数据正确性,需要将ValidationRule类中的ValidatesOnTargetUpdated属性设置为true。
有些时候,还需要为显示Validation方法返回的ValidationResult中的errorContent这条消息。这需用将Binding的NotifyOnValidationError设为true,这样才能将Binding发出的信号传播出去,这叫做路由(Route)。
Coding:
<Window x:Class="BindindValidation.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="140" Width="300"><StackPanel><TextBox x:Name="tb1" Width="200" Margin="5"></TextBox><Slider x:Name="sd1" Width="200" Margin="5" Maximum="100" Minimum="-10"></Slider></StackPanel></Window>public class RangeValidationRule : ValidationRule{public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo){double d = 0;
if (double.TryParse(value.ToString(), out d)){if (d >= 0 && d <= 100)
{return new ValidationResult(true, null);}}return new ValidationResult(false, "Validation Failed!");}}public MainWindow()
{InitializeComponent();Binding binding = new Binding("Value") { Source = this.sd1 };binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;RangeValidationRule rvr = new RangeValidationRule();
rvr.ValidatesOnTargetUpdated = true;
binding.ValidationRules.Add(rvr);binding.NotifyOnValidationError = true;
this.tb1.SetBinding(TextBox.TextProperty, binding);
this.tb1.AddHandler(Validation.ErrorEvent, new RoutedEventHandler(this.ValidationError));}
Binding的数据装换
有时候,Binding的Source与Target两边的Binding的值类型不一样,就会用到Binding的一种机制叫做数据转换。比如以上列子,Textbox的Text属性为String类型,Slider的Value属性为Double类型,这里就用到了这种机制实现的,简单的转换,WPF已经帮我们实现了。
自己写Converter,是要创建一个实现了IValueConverter接口,定义如下:
public interface IValueConverter{object Convert(object value, Type targetType, object parameter, CultureInfo cultrue);object ConvertBack(object value, Type targetType, object parameter, CultureInfo cultrue);}
Convert方法用于Source流向Target时,反之ConvertBack。
Coding:
<Window x:Class="BindindValidation.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local ="clr-namespace:BindindValidation"
Title="MainWindow" Height="272" Width="300"><Window.Resources><local:CategoryToSourceConverter x:Key="cts"></local:CategoryToSourceConverter>
<local:StateToNullableBoolConverter x:Key="sts"/>
</Window.Resources><StackPanel><ListBox x:Name="PlaneListBox" Height="160" Margin="5"><ListBox.ItemTemplate><DataTemplate><StackPanel Orientation="Horizontal">
<Image Width="20" Height="20" Source="{Binding Path=Category,Converter={StaticResource cts}}"></Image><TextBlock Text="{Binding Path=Name}" Width="60" Margin="50,0"></TextBlock><CheckBox IsThreeState="True" IsChecked="{Binding Path=State, Converter={StaticResource sts}}"></CheckBox></StackPanel></DataTemplate></ListBox.ItemTemplate></ListBox><Button x:Name="buttonLoad" Content="Load" Height="25" Margin="5,0" Click="buttonLoad_Click"></Button><Button x:Name="buttonSave" Content="Save" Height="25" Margin="5,0" Click="buttonSave_Click"></Button></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.Plane,Name = "P-1", State = State.Available},new Plane(){Category=Category.Glider,Name = "G-1", State = State.Available},new Plane(){Category=Category.Plane,Name = "P-2", State = State.Locked},new Plane(){Category=Category.Glider,Name = "G-2", State = State.UnKnown},new Plane(){Category=Category.Plane,Name = "P-3", State = State.UnKnown},new Plane(){Category=Category.Plane,Name = "P-5", State = State.Available},};this.PlaneListBox.ItemsSource = planeList;
}private void buttonSave_Click(object sender, RoutedEventArgs e){StringBuilder sb = new StringBuilder();
foreach (Plane p in this.PlaneListBox.Items){sb.AppendLine(string.Format("Category={0},Name={1},State={2}", p.Category, p.Name, p.State));}File.WriteAllText(@"E:\PlaneList.txt", sb.ToString());
}}public class CategoryToSourceConverter : IValueConverter{public object Convert(object value, Type targetType, object parameter, CultureInfo culture){Category c = (Category)value;
switch (c)
{case Category.Glider:
return @"\img\glider.png";case Category.Plane:
return @"\img\plane.png";default:
return null;}}public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture){throw new NotImplementedException();}}public class StateToNullableBoolConverter : IValueConverter{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;}}public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture){bool? b = (bool?)value;switch (b)
{case true:return State.Available;
case false:return State.Locked;
case null:default:
return State.UnKnown;
}}}public enum Category{Glider,Plane}public enum State{Available,Locked,UnKnown}public class Plane{public Category Category { get; set; }
public string Name { get; set; }public State State { get; set; }
}
Run: