Validating Input for Bounded Data : Data Binding « Data « Silverlight






Validating Input for Bounded Data

  

<UserControl x:Class='SilverlightApplication3.MainPage'
    xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' 
    xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
    xmlns:d='http://schemas.microsoft.com/expression/blend/2008' 
    xmlns:mc='http://schemas.openxmlformats.org/markup-compatibility/2006' 
    mc:Ignorable='d' 
    d:DesignWidth='640' 
    d:DesignHeight='480'
    xmlns:local="clr-namespace:SilverlightApplication3">

  <UserControl.Resources>
    <local:EmployeeCollection x:Key="REF_EmployeeCollection"/>
    <DataTemplate x:Key="dtEmployee">
      <StackPanel Orientation="Horizontal">
        <TextBlock Text="{Binding FirstName}" />
        <TextBlock Text="{Binding LastName}" Margin="5,0,0,0"/>
      </StackPanel>
    </DataTemplate>
    <DataTemplate x:Key="dtErrorTooltip">
      <Grid Background="LightBlue" Width="125">
        <Grid.RowDefinitions>
          <RowDefinition Height="Auto"/>
          <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <Rectangle Fill="Red" Margin="2,2,2,2" 
                   Grid.Row="0" HorizontalAlignment="Stretch"/>
        <TextBlock Margin="2,2,2,2" Grid.Row="0" 
                   Text="Error" Foreground="Black" HorizontalAlignment="Center"/>
        <TextBlock  Grid.Row="1" Text="{Binding}" 
                    TextWrapping="Wrap" HorizontalAlignment="Stretch"/>
      </Grid>
    </DataTemplate>
  </UserControl.Resources>

  <StackPanel>
    <ListBox x:Name="lbx_Employees" ItemTemplate="{StaticResource dtEmployee}" 
            ItemsSource="{StaticResource REF_EmployeeCollection}" 
            SelectionChanged="lbx_Employees_SelectionChanged" />
    <Button  x:Name="btn_New" Click="btn_New_Click" Content="New Employee"/>
    <StackPanel x:Name="grid_EmployeeForm">
      <TextBox Text="{Binding FirstName, Mode=TwoWay}"/>
      <TextBox Text="{Binding LastName, Mode=TwoWay}"/>
      <TextBlock Text="Last"/>
      <TextBlock Text="First"/>
      <TextBlock Text="Name"/>
      <TextBlock Text="Street"/>
      <TextBox Text="{Binding Address.Street, Mode=TwoWay}"/>
      <TextBlock Text="City"/>
      <TextBlock Text="State"/>
      <TextBlock Text="Zip"/>
      <TextBox Text="{Binding Address.City, Mode=TwoWay}"/>
      <StackPanel BindingValidationError="TextBox_BindingValidationError">
        <TextBox Text="{Binding Address.State, Mode=TwoWay, 
                ValidatesOnExceptions=True,NotifyOnValidationError=True}" 
                BindingValidationError="TextBox_BindingValidationError" 
                 x:Name="State">
        </TextBox>
        <TextBlock Visibility="Collapsed" x:Name="State_ErrorIndicator">
          <ToolTipService.ToolTip>                    
             <ContentControl ContentTemplate="{StaticResource dtErrorTooltip}" 
                             x:Name="State_TooltipContent"/>
          </ToolTipService.ToolTip>
        </TextBlock>
      </StackPanel>
      <StackPanel BindingValidationError="TextBox_BindingValidationError">
        <TextBox Text="{Binding Address.ZipCode, Mode=TwoWay,ValidatesOnExceptions=True,NotifyOnValidationError=True}" 
                  BindingValidationError="TextBox_BindingValidationError" 
                  x:Name="ZipCode"/>
        <TextBlock Visibility="Collapsed" x:Name="ZipCode_ErrorIndicator">
        <ToolTipService.ToolTip>                    
           <ContentControl ContentTemplate="{StaticResource dtErrorTooltip}" x:Name="ZipCode_TooltipContent"/>
        </ToolTipService.ToolTip>
        </TextBlock>
      </StackPanel>
      <TextBlock Text="Phone" TextWrapping="Wrap"/>
      <StackPanel BindingValidationError="TextBox_BindingValidationError" 
            HorizontalAlignment="Stretch"  VerticalAlignment="Stretch" >
        <TextBox Text="{Binding PhoneNum, Mode=TwoWay, 
          ValidatesOnExceptions=True,NotifyOnValidationError=True}" 
          BindingValidationError="TextBox_BindingValidationError" 
          x:Name="PhoneNum"/>
        <TextBlock Visibility="Collapsed" x:Name="PhoneNum_ErrorIndicator">
          <ToolTipService.ToolTip>                    
             <ContentControl ContentTemplate="{StaticResource dtErrorTooltip}" 
                             x:Name="PhoneNum_TooltipContent"/>
          </ToolTipService.ToolTip>
        </TextBlock>
      </StackPanel>
      <Button Content="Close" x:Name="btnClose" Click="btnClose_Click"/>
    </StackPanel>
  </StackPanel>
</UserControl>

    
//File: Page.xaml.cs
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;

namespace SilverlightApplication3
{
  public class Employee : INotifyPropertyChanged
  {
    public event PropertyChangedEventHandler PropertyChanged;
    private void RaisePropertyChanged(PropertyChangedEventArgs e)
    {
      if (PropertyChanged != null)
        PropertyChanged(this, e);
    }

    public Employee()
    {
    }

    private string _FirstName;
    public string FirstName
    {
      get { return _FirstName; }
      set
      {
        string OldVal = _FirstName;
        if (OldVal != value)
        {
          _FirstName = value;
          RaisePropertyChanged(new PropertyChangedEventArgs("FirstName"));
        }
      }
    }
    private string _LastName;
    public string LastName
    {
      get { return _LastName; }
      set
      {
        string OldVal = _LastName;
        if (OldVal != value)
        {
          _LastName = value;
          RaisePropertyChanged(new PropertyChangedEventArgs("LastName"));
        }
      }
    }
    private long _PhoneNum;
    public long PhoneNum
    {
      get { return _PhoneNum; }
      set
      {
        long OldVal = _PhoneNum;

        if (value.ToString().Length != 10)
          throw new Exception("Phone Number has to be exactly 10 digits");

        if (OldVal != value)
        {
          _PhoneNum = value;
          RaisePropertyChanged(new PropertyChangedEventArgs("PhoneNum"));
        }
      }
    }
    private Address _Address;
    public Address Address
    {
      get { return _Address; }
      set
      {
        Address OldVal = _Address;
        if (OldVal != value)
        {
          _Address = value;
          RaisePropertyChanged(new PropertyChangedEventArgs("Address"));
        }
      }
    }
  }

  public class Address : INotifyPropertyChanged
  {
    public event PropertyChangedEventHandler PropertyChanged;
    private void RaisePropertyChanged(PropertyChangedEventArgs e)
    {
      if (PropertyChanged != null)
        PropertyChanged(this, e);
    }

    private string _Street;
    public string Street
    {
      get { return _Street; }
      set
      {
        string OldVal = _Street;
        if (OldVal != value)
        {
          _Street = value;
          RaisePropertyChanged(new PropertyChangedEventArgs("Street"));
        }
      }
    }
    private string _City;
    public string City
    {
      get { return _City; }
      set
      {
        string OldVal = _City;

        if (OldVal != value)
        {
          _City = value;
          RaisePropertyChanged(new PropertyChangedEventArgs("City"));
        }
      }
    }
    private string _State;
    public string State
    {
      get { return _State; }
      set
      {
        string OldVal = _State;
        if (value.Length != 2)
          throw new Exception("State needs to be the 2 letter abbreviation for the US State");

        if (OldVal != value)
        {
          _State = value;
          RaisePropertyChanged(new PropertyChangedEventArgs("State"));
        }
      }
    }
    private int _ZipCode;
    public int ZipCode
    {
      get { return _ZipCode; }
      set
      {
        int OldVal = _ZipCode;
        if (value.ToString().Length != 5)
          throw new Exception("Zipcode needs to be exactly 5 digits");
        if (OldVal != value)
        {
          _ZipCode = value;
          RaisePropertyChanged(new PropertyChangedEventArgs("ZipCode"));
        }
      }
    }
  }

  public class EmployeeCollection : ICollection<Employee>, IList<Employee>, INotifyCollectionChanged
  {
    private List<Employee> _internalList;

    public EmployeeCollection(){
      _internalList = new List<Employee>();
    }

    public event NotifyCollectionChangedEventHandler CollectionChanged;

    private void RaiseCollectionChanged(NotifyCollectionChangedEventArgs e)
    {
      if (CollectionChanged != null)
      {
        CollectionChanged(this, e);
      }
    }
    public void Add(Employee item)
    {
      _internalList.Add(item);
      RaiseCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add,item, _internalList.Count - 1));
    }
    public void Clear()
    {
      _internalList.Clear();
      RaiseCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
    }
    public bool Remove(Employee item)
    {
      int idx = _internalList.IndexOf(item);
      bool RetVal = _internalList.Remove(item);
      if (RetVal)
        RaiseCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove,item, idx));
      return RetVal;
    }
    public void RemoveAt(int index)
    {
      Employee item = null;
      if (index < _internalList.Count)
        item = _internalList[index];
      _internalList.RemoveAt(index);
      if (index < _internalList.Count)
        RaiseCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove,item, index));
    }
    public void Insert(int index, Employee item)
    {
      _internalList.Insert(index, item);
      RaiseCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add,item, index));
    }
    public Employee this[int index]
    {
      get { return _internalList[index]; }
      set
      {
        _internalList[index] = value;
        RaiseCollectionChanged(
          new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace,
            value, index));

      }
    }

    public bool Contains(Employee item)
    {
      return _internalList.Contains(item);
    }
    public void CopyTo(Employee[] array, int arrayIndex)
    {
      _internalList.CopyTo(array, arrayIndex);
    }
    public int Count
    {
      get { return _internalList.Count; }
    }
    public bool IsReadOnly
    {
      get { return ((IList<Employee>)_internalList).IsReadOnly; }
    }
    public IEnumerator<Employee> GetEnumerator()
    {
      return _internalList.GetEnumerator();
    }
    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
      return (System.Collections.IEnumerator)_internalList.GetEnumerator();
    }
    public int IndexOf(Employee item)
    {
      return _internalList.IndexOf(item);
    }
  }

  public partial class MainPage : UserControl
  {
    public MainPage()
    {
      InitializeComponent();
      EmployeeCollection empColl = (EmployeeCollection)lbx_Employees.ItemsSource;
      empColl.Add(new Employee
      {
        FirstName = "A",
        LastName = "B",
        PhoneNum = 2,
        Address = new Address
        {
          Street = "2 Street",
          City = "New York",
          State = "NY",
          ZipCode = 10006
        }
      });

      empColl.Add(new Employee
      {
        FirstName = "A",
        LastName = "B",
        PhoneNum = 7,
        Address = new Address
        {
          Street = "1 Street",
          City = "New York",
          State = "NY",
          ZipCode = 10007
        }
      });

      empColl.Add(new Employee
      {
        FirstName = "N",
        LastName = "M",
        PhoneNum = 7,
        Address = new Address
        {
          Street = "1 Road",
          City = "New York",
          State = "NY",
          ZipCode = 10016
        }
      });
    }

    private void btn_New_Click(object sender, RoutedEventArgs e)
    {
      EmployeeCollection empColl = (EmployeeCollection)lbx_Employees.ItemsSource;
      Employee newEmp = new Employee();
      newEmp.Address = new Address();
      empColl.Add(newEmp);
      lbx_Employees.SelectedItem = newEmp;
    }

    private void lbx_Employees_SelectionChanged(object sender,SelectionChangedEventArgs e)
    {
      grid_EmployeeForm.DataContext = (Employee)lbx_Employees.SelectedItem;
      grid_EmployeeForm.Visibility = Visibility.Visible;
      
    }

    private void btnClose_Click(object sender, RoutedEventArgs e)
    {
      grid_EmployeeForm.Visibility = Visibility.Collapsed;
      
    }

    private void TextBox_BindingValidationError(object sender,
      ValidationErrorEventArgs e)
    {
      if (e.Action == ValidationErrorEventAction.Added)
      {
        if (sender is TextBox)
        {
          (sender as TextBox).Background = new SolidColorBrush(Colors.Red);
        }
        else if (sender is Grid)
        {
          TextBlock errorInd = (sender as Grid).FindName((e.OriginalSource as TextBox).Name + "_ErrorIndicator") as TextBlock;
          errorInd.Visibility = Visibility.Visible;
          errorInd.Text = "*";
          ContentControl tooltipContent = errorInd.FindName((e.OriginalSource as TextBox).Name + "_TooltipContent") as ContentControl;
          tooltipContent.Content = e.Error.Exception.Message;
        }
      }
      else
      {
        if (sender is TextBox)
        {
          (sender as TextBox).Background = new SolidColorBrush(Colors.Transparent);
        }
        else if (sender is Grid)
        {
          ((sender as Grid).FindName((e.OriginalSource as TextBox).Name + "_ErrorIndicator") as TextBlock).Visibility = Visibility.Collapsed; ;
        }
      }
    }
  }
}

   
    
  








Related examples in the same category

1.Binding Application Data to the UIBinding Application Data to the UI
2.Receiving Change Notifications for Bound Data
3.DataBinding and INotifyPropertyChanged
4.Implementing Data Binding in Silverlight ApplicationsImplementing Data Binding in Silverlight Applications
5.Bind to a collection
6.Add a value converter to a binding using XAML
7.Without Binding
8.Text Data Binding
9.Bind to an Existing Object InstanceBind to an Existing Object Instance
10.Binding FontFamily / FontSize value for current ControlBinding FontFamily / FontSize value for current Control
11.Binding an Emoticon object to a GridBinding an Emoticon object  to a Grid
12.Binding a collection of Emoticon objects to a ListBox through the ItemsSource propertyBinding a collection of Emoticon objects to a ListBox through the ItemsSource property