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 = "";                
            }

        }

程序的運行結果如下:

 附:程序完整的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>

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM