I have the following validation method in my viewmodel (example is showing only one column, "ItemNumber"):
public bool IsValid
{
get
{
foreach (string property in ValidatedProperties)
if (GetValidationError(property) != null)
return false;
return true;
}
}
static readonly string[] ValidatedProperties =
{
"ItemNumber"
};
string GetValidationError(string propertyName)
{
if (Array.IndexOf(ValidatedProperties, propertyName) < 0)
return null;
string error = null;
switch (propertyName)
{
case "ItemNumber":
error = this.ValidateItemNumber();
break;
default:
Debug.Fail("Unexpected property being validated on ProjectExpense: " + propertyName);
break;
}
// set the status message on the UI to the generated error
if (error != null)
{
ErrorMessage = error;
}
return error;
}
// string method
static bool IsStringMissing(string value)
{
return String.IsNullOrEmpty(value) || value.Trim() == String.Empty;
}
string ValidateItemNumber()
{
if (SelectedProjectExpenseItem != null)
{
if (IsStringMissing(SelectedProjectExpenseItem.ItemNumber))
{
return "Item number is required";
}
if (SelectedProjectExpenseItem.ItemNumber.Length > 50)
{
return "Item number exceeds 50 characters";
}
}
return null;
}
#endregion
#region IDataErrorInfo Members
string IDataErrorInfo.Error { get { return null; } }
string IDataErrorInfo.this[string propertyName]
{
get { return this.GetValidationError(propertyName); }
}
The validation fires, but I don't know how to communicate it to my datagrid. I am using a separate Dto (hence SelectedProjectExpenseItem.ItemNumber above, SelectedProjectExpenseItem is my Dto) instead of having the properties directly in my viewmodel. Here is my datagrid:
<DataGrid ItemsSource="{Binding Path=ListOfProjectExpenseItems}" AutoGenerateColumns="False"
Name="dgProjectExpenseItems" SelectionMode="Single" SelectionUnit="FullRow" CanUserResizeColumns="True"
SelectedItem="{Binding Path=SelectedProjectExpenseItem, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" GridLinesVisibility="Horizontal" CanUserDeleteRows="True" CanUserAddRows="True">
<DataGrid.Columns>
<DataGridTextColumn Header="ID" Width="SizeToCells" MinWidth="50" Binding="{Binding RowID}" />
<DataGridTextColumn Header="Project Expense ID" Width="SizeToCells" Visibility="Hidden" MinWidth="0" Binding="{Binding ProjectExpenseID, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<DataGridTextColumn Header="Item Number" Width="SizeToCells" MinWidth="140" Binding="{Binding ItemNumber, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<DataGridTextColumn Header="Item Description" Width="SizeToCells" MinWidth="250" Binding="{Binding ItemDescription, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<DataGridTextColumn Header="Unit Price" Width="SizeToCells" MinWidth="90" Binding="{Binding ItemUnitPrice, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<DataGridTextColumn Header="Qty" Width="SizeToCells" MinWidth="65" Binding="{Binding ItemQty, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<DataGridTextColumn Header="Supplier Name" Width="SizeToCells" MinWidth="200" Binding="{Binding SupplierName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</DataGrid.Columns>
</DataGrid>
I would like to use a style, say with a red border and tooltip stating the error, to signify a problem with the row or cell. Every example I found using styles, however, has the properties directly in the viewmodel, and I cannot figure out how to port it over to my Dto.
Any help is appreciated.
The problems had to do with using Dto's in my implementation, or at least the lack of implementing IDataErrorInfo in them. I decided to dump them and go with straight business objects that implement IDataErroInfo and wa-la, everything works beautifully now.