Silverlight中的数据绑定3

数据转换

Silverlight中实现数据转换的机制与ASP.NET应该讲是同样的思想,只不过ASP.NET中似乎淡化了手动编写关于数据转换的部分,在Silverlight中我们实现数据转换需实现接口IValueConverter,其位于System.Windows.Data中,IValueConverter其包含两个方法:

              Convert():当数据从数据源发送到绑定目标时调用

              ConvertBack():当数据从绑定目标发送回绑定源时调用

只有双向绑定时才需要真正实现这两个方法,当单向绑定时,只需实现Convert(),对于ConvertBack()可以使用throw new NotImplementException形式的代码填充。下面仍然以之前的示例为基础,实现FirstName与LastName中的内容为首字母大写形式。

首先仍然沿用先前的Person类:

 public class Person:INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        public Person() { }
        private string firstName;
        public string FirstName
        {
            get { return firstName; }
            set { firstName = value;
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs("FirstName"));
            }
            }
        }
        private string lastName;
        public string LastName
        {
            get { return lastName; }
            set { 
                lastName = value;
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs("LastName"));
                }
            }
        }
}

然后实现一个基于IValueConverter的类,完整代码:

namespace DataBindSilverlight
{
    public class UCFirst:IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            var name = (string)value;
            if (name.Length > 0)
            {
                var firstname = name.Substring(0,1);
                name = firstname.ToUpper() + name.Substring(1);
            }
            return name;
        }
        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return (string)value;
        }
    }
}

这两步工作完成后,下面的工作即是需要在XAML标记中告知Silverlight使用此转换器,首先,定义一个XML前缀,使得XAML可以访问DataBindSilverlight 空间中的类,代码为:<Canvas xmlns:local="clr-namespace:DataBindSilverlight"/> 第二步则是创建一个Resource子元素,其可以使用DataBindSilverlight,包括UCfirst转换器,这里我们将UCfirst作为内部资源加载,代码:

           <Canvas.Resources>
              <local:UCFirst x:Key="ucfirstConverter"></local:UCFirst>
           </Canvas.Resources>

以上代码添加了一个键x:Key,用来对资源的引用,接下来在TextBox元素中提供转换器的名称

<TextBox  Name="textBlock4" Text="{Binding LastName, Mode=TwoWay,Converter={StaticResource ucfirstConverter}}"  />

关键字StaticResouces表示使用的资源是内部资源,ucfirstConverter是分配给<local:UCFirst/>的键值。 那么我们已经完成了整个XAML的代码的设计:

代码
代码
<Grid x:Name="PersonalPanel" Background="White">
<Canvas xmlns:local="clrnamespace:DataBindSilverlight">
<Canvas.Resources>
<local:UCFirst x:Key="ucfirstConverter"></local:UCFirst>
</Canvas.Resources>
<TextBox Height="23" HorizontalAlignment="Left" Margin="88,53,0,0" Name="textBlock3" Text="{Binding FirstName,Mode=TwoWay,ValidatesOnExceptions=True,NotifyOnValidationError=True}"BindingValidationError="showError"VerticalAlignment="Top" />
  <TextBox Height="23" HorizontalAlignment="Left" Margin="89,89,0,0" Name="textBlock4" Text="{Binding LastName, Mode=TwoWay, Converter={StaticResource ucfirstConverter},ValidatesOnExceptions=True,NotifyOnValidationError=True}" BindingValidationError="showError" VerticalAlignment="Top" />
  <Canvas Canvas.Left="120">
<Polygon Fill="Black" Points="0,5,10,0,10,10" MouseLeftButtonDown="prev"></Polygon>
<Polygon Fill="Black" Points="15,0,15,10,25,5" MouseLeftButtonDown="next"></Polygon>
<TextBlock Text="Reverse" Canvas.Left="40" Canvas.Top="20" FontSize="13" MouseLeftButtonDown="reverse"></TextBlock>
</Canvas>
</Canvas>
</Grid>

后台代码其实没有变化,为了方便,仍然贴出来  

        private int pos = -1;
        private Person[] persons;
        public MainPage()
        {
            InitializeComponent();          
            persons = new Person[] 
            {
             new Person{FirstName="david",LastName="Grenn"},
             new Person{FirstName="dam",LastName="white"},
             new Person{FirstName="tom",LastName="Smith"},
            };         
        }
        public void prev(object sender, MouseButtonEventArgs e)
        {
            if (pos > 0)
                pos--;
            bind();
        }
        public void next(object sender, MouseButtonEventArgs e)
        {
            if (pos < persons.Length - 1)
                pos++;
            bind();
        }
        private void bind()
        {
            PersonalPanel.DataContext = persons[pos];
        }

尽管在硬编码中,我们看到的是小写字母单词呈现的单词,但是运行时,已经成功的将其首字母改变为大写形式。

数据验证

当绑定的数据发生更改时,如果需要确保新数据仍然符合某些预先设定的规则,我们基于前面的数据转换示例扩展这一功能首先更新XAML文件,在TextBox元素中提供绑定信息时设置ValidatesOnExceptionsNotifyOnValidationError两个属性为True

 XAML完整代码: 

<Grid x:Name="PersonalPanel" Background="White">
<Canvas xmlns:local="clr-namespace:DataBindSilverlight">
<Canvas.Resources>
<local:UCFirst x:Key="ucfirstConverter"></local:UCFirst>
</Canvas.Resources>
<TextBox Height="23" HorizontalAlignment="Left" Margin="88,53,0,0" Name="textBlock3" Text="{Binding FirstName, Mode=TwoWay,ValidatesOnExceptions=True,NotifyOnValidationError=True}" BindingValidationError="showError" VerticalAlignment="Top" />
<TextBox Height="23" HorizontalAlignment="Left" Margin="89,89,0,0" Name="textBlock4" Text="{Binding LastName, Mode=TwoWay, Converter={StaticResource ucfirstConverter},ValidatesOnExceptions=True,NotifyOnValidationError=True}" BindingValidationError="showError" VerticalAlignment="Top" />
<Canvas Canvas.Left="120">
<Polygon Fill="Black" Points="0,5,10,0,10,10" MouseLeftButtonDown="prev"></Polygon>
<Polygon Fill="Black" Points="15,0,15,10,25,5" MouseLeftButtonDown="next"></Polygon>
<TextBlock Text="Reverse" Canvas.Left="40" Canvas.Top="20" FontSize="13" MouseLeftButtonDown="reverse"></TextBlock>
</Canvas>
</Canvas>
</Grid>

 注意BindingValidationError设置了出现异常的事件处理程序,showError方法的第2个参数类型为ValidationErrorEventArgs, 可通过访问该参数获取相关信息,

  public void showError(object sender,ValidationErrorEventArgs e)
        {
            //异常不会冒泡
              e.Handled = true;
            if (e.Action == ValidationErrorEventAction.Added)
            {
             (e.OriginalSource as TextBox).Text = "**Error**";            }       
        }

ValidationErrorEventAction枚举包含2个值:Added  新验证错误已经信号

                                                           Removed  之前的错误输入已经纠正

运行后,当输入的值为空时,异常会抛出(F5忽略该异常),单击前进或后退,返回该记录时,文本会发送改变 

posted @ 2010-05-16 18:21  ringgo  阅读(945)  评论(1编辑  收藏  举报