WPF Binding转换与校验

Binding是WPF的核心,而数据的转换与校验是与Binding配套的,其重要性不言而喻,前面介绍了WPF的Binding,现在来看下Converter&Validation。本文目标是以简单的Demo展示Converter&Validation的用法。

Binding用于数据有效性校验的是Binding的ValidationRules属性,用于数据类型转换的是Binding的Converter属性

当Source端Path所关联的数据与Target目标属性数据类型不一致是,我们可以添加数据转换器。给出一个Demo。

首先在xaml界面中定义一个Grid。

     <Grid>

        <TextBlock x:Name="txtMsg" Text="{Binding ElementName=txtBox, Path=(Validation.Errors)[0].ErrorContent}" Foreground="Red" FontWeight="Bold" Margin="34,12,161,280" />



        <DataGrid  AutoGenerateColumns="False" Margin="34,48,44,21" Name="dataGrid1" DataContext="{Binding}">

            <DataGrid.Columns>

                <DataGridTemplateColumn Header="Id" Width="*" IsReadOnly="True">

                    <DataGridTemplateColumn.CellTemplate>

                        <DataTemplate>

                            <TextBlock  FontSize="16" Text="{Binding Id}" Background="{Binding Id,Converter={StaticResource IdConverter1}}"/>

                        </DataTemplate>

                    </DataGridTemplateColumn.CellTemplate>

                </DataGridTemplateColumn>

                <DataGridTemplateColumn Header="Name" Width="2*" IsReadOnly="True">

                    <DataGridTemplateColumn.CellTemplate>

                        <DataTemplate>

                            <!--<TextBlock Text="{Binding Name}"/>-->

                            <TextBlock x:Name="txtBox"  Validation.ErrorTemplate="{StaticResource errorTemplate}" Validation.Error="txtBox_Error" >

                                <TextBlock.Text>

                                    <Binding Path="Name" NotifyOnValidationError="True" >

                                        <Binding.ValidationRules>

                                            <local:NameValidationRule  ValidatesOnTargetUpdated="True" />

                                        </Binding.ValidationRules>

                                    </Binding>

                                </TextBlock.Text>

                            </TextBlock>

                        </DataTemplate>

                    </DataGridTemplateColumn.CellTemplate>

                </DataGridTemplateColumn>

                <DataGridTemplateColumn Header="Age" Width="*" IsReadOnly="True">

                    <DataGridTemplateColumn.CellTemplate>

                        <DataTemplate>

                            <TextBlock Text="{Binding Age}"/>

                        </DataTemplate>

                    </DataGridTemplateColumn.CellTemplate>

                </DataGridTemplateColumn>

            </DataGrid.Columns>



        </DataGrid>

    </Grid>

下面自定义一个DataTable对象,作为Grid的数据源。

using System.Data;



namespace ConverterAndValidation

{

   public class ClassData

    {

        /// <summary>

        /// 手动创建一个DataTable

        /// </summary>

        /// <returns></returns>

        public static DataTable GetDataTable()

        {

            DataTable dt = new DataTable();

            dt.Columns.Add("Id");

            dt.Columns.Add("Name");

            dt.Columns.Add("Age");

            //

            for (int i = 1; i <= 10; i++)

            {

                DataRow dr = dt.NewRow();

                dr.ItemArray = new object[] { i, "DebugLZQ"+i, 25+i };

                dt.Rows.Add(dr);

            }



            return dt;

        }

    }

}

Binding如下:

DataTable dt = ClassData.GetDataTable();

dataGrid1.ItemsSource = dt.DefaultView;

为了进行转换需要实现IValueConverter接口

using System;

using System.Windows.Data;

using System.Windows.Media;



namespace ConverterAndValidation

{

    class IdConverter:IValueConverter

    {

        #region IValueConverter 成员



        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)

        {            

            int id = int.Parse(value.ToString());

            if (id == 1)

                return new SolidColorBrush(Colors.Silver );

            if (id == 2)

                return new SolidColorBrush(Colors.Teal );

            else

                return new SolidColorBrush(Colors.Gold );

        }



        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)

        {

            throw new NotImplementedException();

        }



        #endregion

    }

}

如何消费这个IdConverter呢?
添加一个xmlns

xmlns:local="clr-namespace:ConverterAndValidation"

添加Window.Resources资源

<local:IdConverter x:Key="IdConverter1"/>

在Binding处

<TextBlock  FontSize="16" Text="{Binding Id}" Background="{Binding Id,Converter={StaticResource IdConverter1}}"/>

下面同样以这个例子,写数据校验的Demo。

 为了进行校验,需要准备一个抽象类ValidationRule的派生类。

using System.Windows.Controls;



namespace ConverterAndValidation

{

    class NameValidationRule:ValidationRule

    {

        public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)

        {

            string name = value.ToString();

            if (name!= "DebugLZQ5")

            {

                return new ValidationResult(true, null);

            }

            return new ValidationResult(false, "Error Name,Validation Failed.");

        }

    }

}

如何消费这个Validation?在Window.Resources中添加

<local:NameValidationRule x:Key="NameValidationRule1"/>
        <ControlTemplate x:Key="errorTemplate">

            <!--<StackPanel>

                <TextBlock Foreground="Red">Invalid Value!!!</TextBlock>                

                <AdornedElementPlaceholder/>

            </StackPanel>-->

            <DockPanel>

                <TextBlock Foreground="Red">Invalid Value!!!</TextBlock>

                <AdornedElementPlaceholder/>

            </DockPanel>

        </ControlTemplate>

Binding部分

<TextBlock x:Name="txtBox"  Validation.ErrorTemplate="{StaticResource errorTemplate}" Validation.Error="txtBox_Error" >

   <TextBlock.Text>

      <Binding Path="Name" NotifyOnValidationError="True" >

          <Binding.ValidationRules>

             <local:NameValidationRule  ValidatesOnTargetUpdated="True" />

          </Binding.ValidationRules>

      </Binding>

   </TextBlock.Text>

</TextBlock>

txtBox_Error如下

        private void txtBox_Error(object sender, ValidationErrorEventArgs e)

        {

            if (e.Action == ValidationErrorEventAction.Added)    // Validation Error Occurred

            {

                txtMsg.Text = e.Error.ErrorContent.ToString();                

            }

            else                        // No Error

            {

                txtMsg.Text = "";                

            }



        }

程序的运行结果如下:

WPF Binding转换与校验

 附:程序完整的xaml如下:

View Code
<Window x:Class="ConverterAndValidation.MainWindow"

        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

        

        xmlns:local="clr-namespace:ConverterAndValidation"

        

        Title="MainWindow" Height="350" Width="525">

    <Window.Resources>

        <local:IdConverter x:Key="IdConverter1"/>

        <local:NameValidationRule x:Key="NameValidationRule1"/>

        <ControlTemplate x:Key="errorTemplate">

            <!--<StackPanel>

                <TextBlock Foreground="Red">Invalid Value!!!</TextBlock>                

                <AdornedElementPlaceholder/>

            </StackPanel>-->

            <DockPanel>

                <TextBlock Foreground="Red">Invalid Value!!!</TextBlock>

                <AdornedElementPlaceholder/>

            </DockPanel>

        </ControlTemplate>

   

    </Window.Resources>



    <Grid>

        <TextBlock x:Name="txtMsg" Text="{Binding ElementName=txtBox, Path=(Validation.Errors)[0].ErrorContent}" Foreground="Red" FontWeight="Bold" Margin="34,12,161,280" />



        <DataGrid  AutoGenerateColumns="False" Margin="34,48,44,21" Name="dataGrid1" DataContext="{Binding}">

            <DataGrid.Columns>

                <DataGridTemplateColumn Header="Id" Width="*" IsReadOnly="True">

                    <DataGridTemplateColumn.CellTemplate>

                        <DataTemplate>

                            <TextBlock  FontSize="16" Text="{Binding Id}" Background="{Binding Id,Converter={StaticResource IdConverter1}}"/>

                        </DataTemplate>

                    </DataGridTemplateColumn.CellTemplate>

                </DataGridTemplateColumn>

                <DataGridTemplateColumn Header="Name" Width="2*" IsReadOnly="True">

                    <DataGridTemplateColumn.CellTemplate>

                        <DataTemplate>

                            <!--<TextBlock Text="{Binding Name}"/>-->

                            <TextBlock x:Name="txtBox"  Validation.ErrorTemplate="{StaticResource errorTemplate}" Validation.Error="txtBox_Error" >

                                <TextBlock.Text>

                                    <Binding Path="Name" NotifyOnValidationError="True" >

                                        <Binding.ValidationRules>

                                            <local:NameValidationRule  ValidatesOnTargetUpdated="True" />

                                        </Binding.ValidationRules>

                                    </Binding>

                                </TextBlock.Text>

                            </TextBlock>

                        </DataTemplate>

                    </DataGridTemplateColumn.CellTemplate>

                </DataGridTemplateColumn>

                <DataGridTemplateColumn Header="Age" Width="*" IsReadOnly="True">

                    <DataGridTemplateColumn.CellTemplate>

                        <DataTemplate>

                            <TextBlock Text="{Binding Age}"/>

                        </DataTemplate>

                    </DataGridTemplateColumn.CellTemplate>

                </DataGridTemplateColumn>

            </DataGrid.Columns>



        </DataGrid>

    </Grid>

</Window>

 

你可能感兴趣的:(bind)