Highlighting an invalid field indicates that the field needs attention, but it does not tell the user why. Feedback should be provided describing the nature of the error and how it can be corrected. In Silverlight for the browser, this is achieved using the ValidationSummary
control. Unfortunately, no such control exists in the Windows Phone FCL. But that does not stop us from making our own!
Included in the downloadable sample code is a simple control for displaying all errors that occur on a page. It is named the same as its browser counterpart: ValidationSummary
. When placed on a page, it retrieves the page and subscribes the page’s BindingValidationError
event during its Loaded
event. When an unhandled validation error occurs for any control on the page, the error is placed in an ObservableCollection
and displayed in the view (see Listing 26.2).
public partial class ValidationSummary : UserControl
{
readonly ObservableCollection<object> errors
= new ObservableCollection<object>();
readonly Dictionary<string, List<object>> errorLookup
= new Dictionary<string, List<object>>();
const int lineHeight = 30;
public IEnumerable<object> Errors
{
get
{
return errors;
}
}
public ValidationSummary()
{
InitializeComponent();
Loaded += HandleLoaded;
}
bool loaded;
void HandleLoaded(object sender, System.Windows.RoutedEventArgs e)
{
if (loaded)
{
return;
}
loaded = true;
Page page = this.GetVisualAncestors<Page>().FirstOrDefault();
if (page == null)
{
throw new InvalidOperationException(
"Unable to locate parent page.");
}
page.BindingValidationError += HandleBindingValidationError;
...
}
/// <summary>
/// Performs property setter validation.
/// </summary>
void HandleBindingValidationError(
object sender, ValidationErrorEventArgs e)
{
string content = e.Error.ErrorContent.ToString();
if (e.Action == ValidationErrorEventAction.Added)
{
AddError(content);
}
else
{
RemoveError(content);
}
}
void AddError(object error)
{
string content = error.ToString();
if (!errors.Contains(content))
{
errors.Add(content);
}
MinHeight += lineHeight;
}
void RemoveError(object error)
{
string content = error.ToString();
errors.Remove(content);
MinHeight -= lineHeight;
}
...
}
The ValidationSummary
control’s XAML file contains a ListBox
, whose ItemsSource
has a data-binding to the Errors
property (see Listing 26.3).
<UserControl x:Class="DanielVaughan.WPUnleashed.ValidationSummary"
x:Name="control"
...
>
<StackPanel x:Name="LayoutRoot"
Background="{StaticResource PhoneBackgroundBrush}">
<ListBox ItemsSource
="{Binding ElementName=control, Path=Errors}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}"
Style="{StaticResource PhoneTextSmallStyle}"
Height="30" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</UserControl>
As soon as the BindingValidationError
event is raised in the host page, the ObservableCollection
of errors is updated, and the user is provided with detailed feedback for each validation error (see Figure 26.9).
13.58.113.193