Rework extension methods that provide more control over binding and validation

This commit is contained in:
2014-06-07 10:14:55 -04:00
parent 2f65bc73f4
commit 822dbeea06

View File

@@ -8,95 +8,128 @@ using System.Windows.Media;
namespace Common.Wpf.Extensions namespace Common.Wpf.Extensions
{ {
public class BindingExpressionInfo
{
public FrameworkElement FrameworkElement { get; private set; }
public BindingExpression BindingExpression { get; private set; }
public BindingExpressionInfo(FrameworkElement frameworkElement, BindingExpression bindingExpression)
{
FrameworkElement = frameworkElement;
BindingExpression = bindingExpression;
}
}
public static class WindowExtensions public static class WindowExtensions
{ {
public static Dictionary<FrameworkElement, BindingExpression> GetExplicitBindingExpressions(this DependencyObject parent) public static List<BindingExpressionInfo> GetBindingExpressions(this DependencyObject parent)
{ {
// Create a dictionary of framework elements and binding expressions return GetBindingExpressions(parent, null);
Dictionary<FrameworkElement, BindingExpression> bindingExpressions = new Dictionary<FrameworkElement, BindingExpression>(); }
public static List<BindingExpressionInfo> GetBindingExpressions(this DependencyObject parent, UpdateSourceTrigger[] triggers)
{
// Create a list of framework elements and binding expressions
var bindingExpressions = new List<BindingExpressionInfo>();
// Get all explict bindings into the list // Get all explict bindings into the list
GetExplicitBindingExpressions(parent, ref bindingExpressions); GetBindingExpressions(parent, triggers, ref bindingExpressions);
return bindingExpressions; return bindingExpressions;
} }
private static void GetExplicitBindingExpressions(DependencyObject parent, ref Dictionary<FrameworkElement, BindingExpression> bindingExpressions) private static void GetBindingExpressions(DependencyObject parent, UpdateSourceTrigger[] triggers, ref List<BindingExpressionInfo> bindingExpressions)
{ {
// Get the number of children // Get the number of children
int childCount = VisualTreeHelper.GetChildrenCount(parent); var childCount = VisualTreeHelper.GetChildrenCount(parent);
// Loop over each child // Loop over each child
for (int childIndex = 0; childIndex < childCount; childIndex++) for (var childIndex = 0; childIndex < childCount; childIndex++)
{ {
// Get the child // Get the child
DependencyObject dependencyObject = VisualTreeHelper.GetChild(parent, childIndex); var dependencyObject = VisualTreeHelper.GetChild(parent, childIndex);
// Check if the object is a tab control // Check if the object is a tab control
if (dependencyObject is TabControl) if (dependencyObject is TabControl)
{ {
// Cast the tab control // Cast the tab control
TabControl tabControl = (dependencyObject as TabControl); var tabControl = (dependencyObject as TabControl);
// Loop over each tab // Loop over each tab
foreach (TabItem tabItem in tabControl.Items) foreach (TabItem tabItem in tabControl.Items)
GetExplicitBindingExpressions((DependencyObject) tabItem.Content, ref bindingExpressions); GetBindingExpressions((DependencyObject) tabItem.Content, triggers, ref bindingExpressions);
} }
else else
{ {
// See if the child is a framework element // Cast to framework element
if (dependencyObject is FrameworkElement) var frameworkElement = dependencyObject as FrameworkElement;
{
// Cast to framework element
FrameworkElement frameworkElement = (FrameworkElement) dependencyObject;
if (frameworkElement != null)
{
// Get the list of properties // Get the list of properties
IEnumerable<DependencyProperty> dependencyProperties = (from PropertyDescriptor propertyDescriptor in TypeDescriptor.GetProperties(dependencyObject) IEnumerable<DependencyProperty> dependencyProperties = (from PropertyDescriptor propertyDescriptor in TypeDescriptor.GetProperties(frameworkElement)
select DependencyPropertyDescriptor.FromProperty(propertyDescriptor) select DependencyPropertyDescriptor.FromProperty(propertyDescriptor)
into dependencyPropertyDescriptor into dependencyPropertyDescriptor
where dependencyPropertyDescriptor != null where dependencyPropertyDescriptor != null
select dependencyPropertyDescriptor.DependencyProperty).ToList(); select dependencyPropertyDescriptor.DependencyProperty).ToList();
// Loop over each dependency property in the list // Loop over each dependency property in the list
foreach (DependencyProperty dependencyProperty in dependencyProperties) foreach (var dependencyProperty in dependencyProperties)
{ {
// Try to get the binding expression for the property // Try to get the binding expression for the property
BindingExpression bindingExpression = frameworkElement.GetBindingExpression(dependencyProperty); var bindingExpression = frameworkElement.GetBindingExpression(dependencyProperty);
// If there is a binding expression and it is set to explicit then make it update the source // If there is a binding expression and it is set to explicit then make it update the source
if (bindingExpression != null && bindingExpression.ParentBinding.UpdateSourceTrigger == UpdateSourceTrigger.Explicit) if (bindingExpression != null && (triggers == null || triggers.Contains(bindingExpression.ParentBinding.UpdateSourceTrigger)))
bindingExpressions.Add(frameworkElement, bindingExpression); bindingExpressions.Add(new BindingExpressionInfo(frameworkElement, bindingExpression));
} }
} }
// If the dependency object has any children then check them // If the dependency object has any children then check them
if (VisualTreeHelper.GetChildrenCount(dependencyObject) > 0) if (VisualTreeHelper.GetChildrenCount(dependencyObject) > 0)
GetExplicitBindingExpressions(dependencyObject, ref bindingExpressions); GetBindingExpressions(dependencyObject, triggers, ref bindingExpressions);
} }
} }
} }
public static void UpdateAllSources(this DependencyObject window) public static void UpdateAllSources(this DependencyObject window, IEnumerable<BindingExpressionInfo> bindingExpressions)
{
UpdateAllSources(window, GetExplicitBindingExpressions(window).Values);
}
public static void UpdateAllSources(this DependencyObject window, IEnumerable<BindingExpression> bindingExpressions)
{ {
foreach (var expression in bindingExpressions) foreach (var expression in bindingExpressions)
expression.UpdateSource(); expression.BindingExpression.UpdateSource();
} }
public static void ClearAllValidationErrors(this DependencyObject window) public static void ClearAllValidationErrors(this DependencyObject window, IEnumerable<BindingExpressionInfo> bindingExpressions)
{
ClearAllValidationErrors(window, GetExplicitBindingExpressions(window).Values);
}
public static void ClearAllValidationErrors(this DependencyObject window, IEnumerable<BindingExpression> bindingExpressions)
{ {
foreach (var expression in bindingExpressions) foreach (var expression in bindingExpressions)
Validation.ClearInvalid(expression); Validation.ClearInvalid(expression.BindingExpression);
}
public static bool Validate(this Window window)
{
// Get a list of all framework elements and binding expressions
var bindingExpressions = window.GetBindingExpressions();
// Loop over each binding expression and clear any existing error
window.ClearAllValidationErrors(bindingExpressions);
// Force all explicit bindings to update the source
window.UpdateAllSources(bindingExpressions);
// See if there are any errors
var hasError = bindingExpressions.Any(b => b.BindingExpression.HasError);
// If there was an error then set focus to the bad controls
if (hasError)
{
// Get the first framework element with an error
var firstErrorElement = bindingExpressions.First(b => b.BindingExpression.HasError).FrameworkElement;
// Set focus
firstErrorElement.Focus();
}
return !hasError;
} }
} }