[索引页][×××]

稳扎稳打Silverlight(15) - 2.0数据之一次绑定, 单向绑定, 双向绑定, INotifyPropertyChanged, 数据转换, 数据验证



作者: webabcd


介绍
Silverlight 2.0 数据绑定:
    Binding - 将绑定目标对象的属性与数据源联接起来
        Source - 绑定的数据源
        Mode - 绑定的数据流的方向 [System.Windows.Data.BindingMode枚举]
            BindingMode.OneTime - 一次绑定。创建绑定时一次性地更新绑定目标对象的属性
            BindingMode.OneWay - 单向绑定(默认值)。数据源的改变会自动通知到绑定目标对象的属性
            BindingMode.TwoWay - 双向绑定。数据源或绑定目标对象的属性的值发生改变时会互相通知。显然,做数据验证的话一定要是双向绑定
        Path - 需要绑定的属性名称
        NotifyOnValidationError - 产生验证错误时是否触发 BindingValidationError 事件。默认值为 false
        ValidatesOnExceptions - 产生验证错误时绑定引擎是否要报告错误。默认值为 false
    INotifyPropertyChanged - 向客户端发出某一属性值已更改的通知
    IValueConverter - 值转换接口,将一个类型的值转换为另一个类型的值。它提供了一种将自定义逻辑应用于绑定的方式
        Convert - 正向转换器。将值从数据源传给绑定目标时,数据绑定引擎会调用此方法
        ConvertBack - 反向转换器。将值从绑定目标传给数据源时,数据绑定引擎会调用此方法
    BindingValidationError - 出现验证错误或解决上次验证错误则触发此事件


在线DEMO
http://webabcd.blog.51cto.com/1787395/342779  


示例
1、NotifyProperty.xaml(演示INotifyPropertyChanged)

<UserControl x:Class="Silverlight20.Data.NotifyProperty" 
    
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"     
    
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> 
    
        <StackPanel HorizontalAlignment="Left"> 
    

                <!-- 
    
                Binding - 将绑定目标对象的属性与数据源联接起来(本例为将 Ellipse的Fill属性 与 MyColor的Brush属性 相联) 
    
                Mode - Binding 的扩展属性之一,默认为 OneWay(单向绑定),即数据源的改变会自动通知到绑定目标对象的属性 
    
                --> 
    
                <Ellipse x:Name="ellipse" Width="100" Height="50" Fill="{Binding Brush, Mode=OneWay}" MouseLeftButtonDown="ellipse_MouseLeftButtonDown" /> 
    

        </StackPanel> 
    
</UserControl>

 

NotifyProperty.xaml.cs

using System; 
    
using System.Collections.Generic; 
    
using System.Linq; 
    
using System.Net; 
    
using System.Windows; 
    
using System.Windows.Controls; 
    
using System.Windows.Documents; 
    
using System.Windows.Input; 
    
using System.Windows.Media; 
    
using System.Windows.Media.Animation; 
    
using System.Windows.Shapes; 
    

using System.ComponentModel; 
    

namespace Silverlight20.Data 
    
{ 
    
         
    public partial 
    class NotifyProperty : UserControl 
    
        { 
    
                MyColor _myColor; 
    

                 
    public NotifyProperty() 
    
                { 
    
                        InitializeComponent(); 
    

                         
    this.Loaded += 
    new RoutedEventHandler(NotifyProperty_Loaded); 
    
                } 
    

                 
    void NotifyProperty_Loaded( 
    object sender, RoutedEventArgs e) 
    
                { 
    
                        _myColor = 
    new MyColor { Brush = 
    new SolidColorBrush(Colors.Red) }; 
    

                         
    // DataContext - FrameworkElement 做数据绑定时的数据上下文  
    
                         
    // 将 MyColor 对象绑定到 Ellipse  
    
                        ellipse.DataContext = _myColor; 
    
                } 
    

                 
    private 
    void ellipse_MouseLeftButtonDown( 
    object sender, MouseButtonEventArgs e) 
    
                { 
    
                         
    // 鼠标按下后修改 MyColor 对象的属性  
    
                         
    // 如果MyColor实现了INotifyPropertyChanged接口,并且绑定目标的BindingMode为OneWay或者TwoWay的话则会自动通知到绑定目标  
    
                         
    if (_myColor.Brush.Color == Colors.Red) 
    
                                _myColor.Brush = 
    new SolidColorBrush(Colors.Green); 
    
                         
    else 
    
                                _myColor.Brush = 
    new SolidColorBrush(Colors.Red); 
    
                } 
    
        } 
    

         
    /* 
         * INotifyPropertyChanged - 向客户端发出某一属性值已更改的通知 
         * 使用 OneWay 或者 TwoWay 的话必须要实现 INotifyPropertyChanged 接口 
        */ 
    
         
    public 
    class MyColor : INotifyPropertyChanged 
    
        { 
    
                 
    private SolidColorBrush _brush; 
    
                 
    public SolidColorBrush Brush 
    
                { 
    
                        get { 
    return _brush; } 
    
                        set 
    
                        { 
    
                                _brush = value; 
    
                                 
    if (PropertyChanged != 
    null) 
    
                                { 
    
                                         
    // 触发 PropertyChanged 事件,事件参数为属性名称  
    
                                        PropertyChanged( 
    this, 
    new PropertyChangedEventArgs( 
    "Brush")); 
    
                                } 
    
                        } 
    
                } 
    

                 
    // 声明一个 PropertyChanged 事件  
    
                 
    public 
    event PropertyChangedEventHandler PropertyChanged; 
    
        } 
    
}

2、Conversion.xaml(演示数据转换)

<!--引用转换器所在的命名空间--> 
    
<UserControl x:Class="Silverlight20.Data.Conversion"     
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"         
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"     
        xmlns:custom="clr-namespace:Silverlight20.Data">     
             
        <UserControl.Resources>     
             
                <!--在资源中声明转换器-->     
                <custom:ColorEnumToBrush x:Key="converter" />     
                     
        </UserControl.Resources>     
             
        <StackPanel HorizontalAlignment="Left">     

                <!--     
                Converter - 用于指定转换器     
                ConverterParameter - 转换器所使用的参数     
                ConverterCulture - 转换器所使用的区域信息     
                -->     
                <Ellipse x:Name="ellipse" Width="100" Height="50" MouseLeftButtonDown="ellipse_MouseLeftButtonDown"         
                        Fill="{Binding ColorEnum, Converter={StaticResource converter}, ConverterParameter=10}"         
                />     

        </StackPanel>     
</UserControl>

Conversion.xaml.cs

using System;     
using System.Collections.Generic;     
using System.Linq;     
using System.Net;     
using System.Windows;     
using System.Windows.Controls;     
using System.Windows.Documents;     
using System.Windows.Input;     
using System.Windows.Media;     
using System.Windows.Media.Animation;     
using System.Windows.Shapes;     

using System.ComponentModel;     
using System.Windows.Data;     

namespace Silverlight20.Data     
{     
             public partial 
    class Conversion : UserControl 
    
        {     
                MyColorEnum _myColorEnum;     

                     public Conversion() 
    
                {     
                        InitializeComponent();     

                             this.Loaded += 
    new RoutedEventHandler(Conversion_Loaded); 
    
                }     

                     void Conversion_Loaded( 
    object sender, RoutedEventArgs e) 
    
                {     
                        _myColorEnum =     new MyColorEnum() { ColorEnum = ColorEnum.Red }; 
    

                             // DataContext - FrameworkElement 做数据绑定时的数据上下文  
    
                             // 将 MyColorEnum 对象绑定到 Ellipse  
    
                        ellipse.DataContext = _myColorEnum;     
                }     

                     private 
    void ellipse_MouseLeftButtonDown( 
    object sender, MouseButtonEventArgs e) 
    
                {     
                             // 鼠标按下后修改 MyColorEnum 对象的属性  
    
                             if (_myColorEnum.ColorEnum == ColorEnum.Red) 
    
                                _myColorEnum.ColorEnum = ColorEnum.Green;     
                             else 
    
                                _myColorEnum.ColorEnum = ColorEnum.Red;     
                }     
        }     

             /* 
         * IValueConverter - 值转换接口,将一个类型的值转换为另一个类型的值。它提供了一种将自定义逻辑应用于绑定的方式 
         *         Convert - 正向转换器。将值从数据源传给绑定目标时,数据绑定引擎会调用此方法 
         *         ConvertBack - 反向转换器。将值从绑定目标传给数据源时,数据绑定引擎会调用此方法 
        */     
             public 
    class ColorEnumToBrush : IValueConverter 
    
        {     
                     /// <summary>  
    
                     /// 正向转换器。将值从数据源传给绑定目标时,数据绑定引擎会调用此方法  
    
                     /// </summary>  
    
                     /// <param name="value">转换之前的值</param>  
    
                     /// <param name="targetType">转换之后的类型</param>  
    
                     /// <param name="parameter">转换器所使用的参数</param>  
    
                     /// <param name="culture">转换器所使用的区域信息</param>  
    
                     /// <returns>转换后的值</returns>  
    
                     public 
    object Convert( 
    object value, Type targetType, 
    object parameter, System.Globalization.CultureInfo culture) 
    
                {     
                             // 将 ColorEnum 类型的值转换为 SolidColorBrush 类型的值  
    

                             // parameter == 10  
    

                        ColorEnum color = (ColorEnum)value;     

                        SolidColorBrush brush =     new SolidColorBrush(Colors.Red); 
    

                             if (color == ColorEnum.Green) 
    
                                brush =     new SolidColorBrush(Colors.Green); 
    

                             return brush; 
    
                }     

                     /// <summary>  
    
                     /// 反向转换器。将值从绑定目标传给数据源时,数据绑定引擎会调用此方法  
    
                     /// </summary>  
    
                     /// <param name="value">转换之前的值</param>  
    
                     /// <param name="targetType">转换之后的类型</param>  
    
                     /// <param name="parameter">转换器所使用的参数</param>  
    
                     /// <param name="culture">转换器所使用的区域信息</param>  
    
                     /// <returns>转换后的值</returns>  
    
                     public 
    object ConvertBack( 
    object value, Type targetType, 
    object parameter, System.Globalization.CultureInfo culture) 
    
                {     
                             return 
    null; 
    
                }     
        }     

             /* 
         * INotifyPropertyChanged - 向客户端发出某一属性值已更改的通知 
         * 使用 OneWay 或者 TwoWay 的话必须要实现 INotifyPropertyChanged 接口 
        */     
             public 
    class MyColorEnum : INotifyPropertyChanged 
    
        {     
                     private ColorEnum _colorEnum; 
    
                     public ColorEnum ColorEnum 
    
                {     
                        get {     return _colorEnum; } 
    
                        set     
                        {     
                                _colorEnum = value;     
                                     if (PropertyChanged != 
    null) 
    
                                {     
                                             // 触发 PropertyChanged 事件,事件参数为属性名称  
    
                                        PropertyChanged(     this, 
    new PropertyChangedEventArgs( 
    "ColorEnum")); 
    
                                }     
                        }     
                }     

                     // 声明一个 PropertyChanged 事件  
    
                     public 
    event PropertyChangedEventHandler PropertyChanged; 
    
        }     

             /// <summary>  
    
             /// 自定义的 ColorEnum 枚举  
    
             /// </summary>  
    
             public 
    enum ColorEnum 
    
        {     
                Red,     
                Green     
        }     
}

3、Validation.xaml(演示数据验证)

<!--引用验证类所在的命名空间--> 
    
<UserControl x:Class="Silverlight20.Data.Validation"     
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"         
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"     
        xmlns:custom="clr-namespace:Silverlight20.Data">     
             
        <!--     
        BindingValidationError - 出现验证错误或解决上次验证错误则触发此事件     
        -->     
        <StackPanel HorizontalAlignment="Left" BindingValidationError="StackPanel_BindingValidationError" >     
                     
                <StackPanel.Resources>     
                     
                        <!--在资源中声明验证类-->     
                        <custom:MyValidation x:Name="myValidation"/>     
                             
                </StackPanel.Resources>     
                     
                <TextBox x:Name="textBox" Width="200" Margin="5">     
                        <TextBox.Text>     
                             
                                <!--     
                                Binding - 将绑定目标对象的属性与数据源联接起来     
                                        Source - 绑定的数据源     
                                        Mode - 绑定的数据流的方向 [System.Windows.Data.BindingMode枚举]     
                                                BindingMode.OneTime - 一次绑定。创建绑定时一次性地更新绑定目标对象的属性     
                                                BindingMode.OneWay - 单向绑定(默认值)。数据源的改变会自动通知到绑定目标对象的属性     
                                                BindingMode.TwoWay - 双向绑定。数据源或绑定目标对象的属性的值发生改变时会互相通知。显然,做数据验证的话一定要是双向绑定     
                                        Path - 需要绑定的属性名称     
                                        NotifyOnValidationError - 产生验证错误时是否触发 BindingValidationError 事件。默认值为 false     
                                        ValidatesOnExceptions - 产生验证错误时绑定引擎是否要报告错误。默认值为 false     
                                -->     
                                <Binding         
                                        Source="{StaticResource myValidation}"         
                                        Mode="TwoWay"         
                                        Path="Count"     
                                        NotifyOnValidationError="True"         
                                        ValidatesOnExceptions="True"     
                                />     
                                             
                        </TextBox.Text>     
                </TextBox>     
                     
                <TextBox x:Name="textBox2" Width="200"    Margin="5" />     
                             
        </StackPanel>     
             
</UserControl>

Validation.xaml.cs

using System;     
using System.Collections.Generic;     
using System.Linq;     
using System.Net;     
using System.Windows;     
using System.Windows.Controls;     
using System.Windows.Documents;     
using System.Windows.Input;     
using System.Windows.Media;     
using System.Windows.Media.Animation;     
using System.Windows.Shapes;     

using System.Text.RegularExpressions;     

namespace Silverlight20.Data     
{     
             public partial     class Validation : UserControl 
    
        {     
                     public Validation()     
                {     
                        InitializeComponent();     
                }     

                     private     void StackPanel_BindingValidationError( 
    object sender, ValidationErrorEventArgs e) 
    
                {     
                             // ValidationErrorEventArgs - 用于提供 BindingValidationError 事件的一些信息      
                             //         ValidationErrorEventArgs.Action - 验证状态      
                             //         ValidationErrorEventArgs.Error - 触发 BindingValidationError 事件的错误信息      
                             //         ValidationErrorEventArgs.Handled - 标记该路由事件是否已被处理      
                             // ValidationErrorEventAction.Added - 因为出现验证错误而触发此事件      
                             // ValidationErrorEventAction.Removed - 因为解决上次验证错误而触发此事件      

                             if (e.Action == ValidationErrorEventAction.Added)     
                        {     
                                textBox.Background =     new SolidColorBrush(Colors.Red);     
                                textBox.Text = e.Error.Exception.Message;     
                        }     
                             else     if (e.Action == ValidationErrorEventAction.Removed) 
    
                        {     
                                textBox.Background =     new SolidColorBrush(Colors.White);     
                        }     
                }     
        }     

             /// <summary>      
             /// 验证类。验证是否为正整数      
             /// </summary>      
             public     class MyValidation 
    
        {     
                     private     string _count; 
    
                     public     string Count 
    
                {     
                        get {     return _count; }     
                        set     
                        {     
                                     if (!Regex.IsMatch(value,     @"^\d+$")) 
    
                                {     
                                             // 绑定引擎可以报告由属性的 setter 抛出的异常,也可以报告由转换器(IValueConverter)抛出的异常      
                                             throw     new Exception( 
    "必须是正整数"); 
    
                                }     

                                _count = value;     
                        }     
                }     
        }     
}

OK