Hello!
I am having a problem with validating ComboBox within a DataGridTemplateColumn.
When I add a new DataGrid record, I need to select a mandatory contact from a Combobox list. If I double click on the Combobox and then select a different record without selecting a value from the list, the validation works and the corresponding TextBlock
borders turn red. This is because the contact ID (FK_Contact_ID) is to zero and the criteria is that FK_Contact_ID should have positive value.
However, if after adding a new record, I select another record without double clicking on the combobox, validation does not take place.
I use SQL Server 2012 and Viusal Studion 2012 with Entity Framework for mapping tables. I have implemented MVVM pattern.
I have included below a snippet of my code; please let me know if more information is required.
What I have noticed is that when I double click on the combobox, after adding a new DataGrid record, the string IDataErrorInfo.this[string columnName] indexer in partial class tblContactAddress gets called, the case "FK_Contact_ID" of switch (columnName)
gets invoked and then ValidationHasError is set to true for the newly added record because FK_Contact_ID is set to zero which is invalid. However, if I select another record, without double clicking on the combobox in the new record the string indexer
does not get called.
Your assistance is greatly appreciated.
Regards
namespace App.Domain { internal interface IContactAddress { [Range(1, int.MaxValue, ErrorMessageResourceName = "ContactMandatory", ErrorMessageResourceType = typeof(Resources))] Int32 FK_Contact_ID { get; set; } } [MetadataType(typeof(IContactAddress))] public partial class tblContactAddress : IContactAddress, IDataErrorInfo { [NonSerialized] private readonly DataErrorInfoSupport dataErrorInfoSupport; public tblContactAddress() { dataErrorInfoSupport = new DataErrorInfoSupport(this); } string IDataErrorInfo.Error { get { return dataErrorInfoSupport.Error; } } string IDataErrorInfo.this[string columnName] { get { switch (columnName) { case "FK_Contact_ID": break; default: result = dataErrorInfoSupport[columnName]; break; } if (string.IsNullOrEmpty(result)) { ValidationHasError = false; result = dataErrorInfoSupport[columnName]; } else { ValidationHasError = true; } return result; } } } }
XAML:
<UserControl x:Class="App.ContactAddressListView" 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" xmlns:c="clr-namespace:App.Converters" mc:Ignorable="d" d:DesignWidth="500" d:DesignHeight="150" ><UserControl.Resources><Style TargetType="{x:Type DataGridCell}"><EventSetter Event="PreviewMouseLeftButtonDown" Handler="DataGridCell_PreviewMouseLeftButtonDown" /></Style><c:StyleConverter x:Key="xStyleConverter" /></UserControl.Resources><DockPanel><DataGrid.Columns><DataGridTemplateColumn Header="{x:Static p:LocalResources.Contact}" x:Name="xContactCBox"><DataGridTemplateColumn.CellTemplate><DataTemplate ><TextBlock Margin="0"><TextBlock.Style><MultiBinding Converter="{StaticResource xStyleConverter}"><Binding Path="FK_Contact_ID" /></MultiBinding></TextBlock.Style><TextBlock.Text><Binding Path="LinkedToContact.ContactName" Mode="OneWay" ValidatesOnDataErrors="True" ValidatesOnExceptions="True" NotifyOnSourceUpdated="True" /></TextBlock.Text></TextBlock></DataTemplate></DataGridTemplateColumn.CellTemplate><DataGridTemplateColumn.CellEditingTemplate><DataTemplate><ComboBox Margin="0" IsEditable="True" ItemsSource="{Binding DataContext.ContactList, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}}" SelectedValue="{Binding Path=FK_Contact_ID, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True, ValidatesOnExceptions=True, NotifyOnValidationError=True}" DisplayMemberPath="ContactName" SelectedValuePath="Contact_ID"></ComboBox></DataTemplate></DataGridTemplateColumn.CellEditingTemplate></DataGridTemplateColumn></DataGrid.Columns></DataGrid></DockPanel></UserControl>
namespace App.Converters { public class StyleConverter: IMultiValueConverter { public object Convert(object[] value, Type targetType, object parameter, CultureInfo culture) { int valueAsDecimal = (int)value[0]; if (valueAsDecimal > 0) return Application.Current.FindResource("TextBlockCellTemplateSytle") as Style; return Application.Current.FindResource("TextBlockVaidationStyle") as Style; } public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) { return null; } } }
Tables:
tblContactAddress >> ContactAddress_ID (int, PK) , FK_Contact_ID (int), Address, other fields...
tblContact >> Contact_ID (int, PK), ContactName (string).
Navigation Property:
LinkedToContact >> (From Role: tblContactAddress, To Role: tblContact)
Abbas