Reputation: 35901
I'm writing a WPF MVVM Light app using Visual Studio 2015. The data has been brought in using Entity Framework 6, using database-first to generate the models. In my MainViewModel.cs file, I'd like to validate the data before doing a SaveChanges()
.
The examples I've seen talk about adding annotations to models (for example, this); however, I'm using auto-generated Entity Framework models. And my ViewModels reference ObservableCollection<Employee>
objects -- nothing references fields directly, so that I can put annotations on them.
Here is the SearchResults
property, which holds the results returned from EF:
private ObservableCollection<Employee> _searchResults;
public ObservableCollection<Employee> SearchResults
{
get { return _searchResults; }
set
{
if (_searchResults == value) return;
_searchResults = value;
RaisePropertyChanged("SearchResults");
}
}
The SearchResults
gets populated after a search and are bound to a DataGrid:
var query = Context.Employees.AsQueryable();
// Build query here...
SearchResults = new ObservableCollection<Employee>(query.ToList());
The user clicks a row on the DataGrid and we show the details for them to update. They can then hit the Save button. But we want to validate the fields in each Employee
before performing Context.SaveChanges()
.
Here's the pertinent area of the partial class Employee
, auto-generated by Entity Framework:
public int employeeID { get; set; }
public int securityID { get; set; }
public string firstName { get; set; }
public string middleName { get; set; }
public string lastName { get; set; }
public string suffix { get; set; }
public string job { get; set; }
public string organizationalUnit { get; set; }
public string costCenter { get; set; }
public string notes { get; set; }
public System.DateTime createdDate { get; set; }
For example, the securityID
must not be blank and it must be an int
, while firstName
and lastName
are required, etc. How do you accomplish this validation and show errors to the user?
Upvotes: 3
Views: 2674
Reputation: 3315
I assume when you show user the details you are using TextBox
es (You can apply the same solution for other controls).
Instead of validating data after the user changes the properties of Employee
, just validate beforehand and don't even change the properties if they are invalid.
You can do this easily with ValidationRule
class. For example:
<ListBox ItemsSource="{Binding Employees}" Name="ListBoxEmployees">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}"></TextBlock>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<TextBox>
<TextBox.Text>
<Binding ElementName="ListBoxEmployees" Path="SelectedItem.Name" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<stackOverflow:NotEmptyStringValidationRule/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
and the validation rule:
public class NotEmptyStringValidationRule : ValidationRule
{
public override ValidationResult Validate(object value, CultureInfo cultureInfo)
{
string s = value as string;
if (String.IsNullOrEmpty(s))
{
return new ValidationResult(false, "Field cannot be empty.");
}
return ValidationResult.ValidResult;
}
}
Also you can disable the Save button when any of the validation rules fail.
Upvotes: 3