In my model I have lots of properties for different objects and I'm checking the value while setting value for object and if the value is not accepted I will throw an exception this was working perfect with windows forms propertygrid but now I'm trying to design a new interface using WPF . in WPF when I bound a property to a control like textbox ,when the value is changed I don't know how to handle the exception and show the error message . example :
public string ConnectionString
{
get
{
return (_ConnectionString);
}
set
{
try
{
_ConnectionString = value ;
_SqlConnection = new System.Data.SqlClient.SqlConnection(_ConnectionString);
_ConnectionTested = true;
}
catch (Exception caught)
{
_ConnectionTested = false;
_TableNameTested = false;
_FieldNameTested = false;
_ConditionTested = false;
_ConnectionString = "";
//----delete values----
ValuesCollection.Clear();
throw (new Exception("Can not Open the connection String \nReason : " + caught.Message ));
}
}
}
and the wpf part is like :
<TextBox TextWrapping="Wrap" x:Name="ConnectionStringTextBox" Text="{Binding Path=ConnectionString, Mode=TwoWay}"/>
is there anyway when the value in textbox is changed check if the model has thrown an exception and then show the exception.message to user ?
thanks
Kent is absolutely correct about using ValidationRule and ExceptionValidationRule. However you will find this solution very unpleasant to use for your situation where you have a lot of bindings to fields like this. In many places you will be replacing something like this:
<TextBox Text="{Binding Value}" />
with this:
<TextBox Validation.ErrorTemplate="{StaticResource errorTemplate}">
<TextBox.Text>
<Binding Path="Value">
<Binding.ValidationRules>
<ExceptionValidationRule />
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
Because this is so unwieldly, I like to create an inherited attached property that automatically applies validation rules, so all I have to say is:
<Window
ValidationHelper.ErrorTemplate="{StaticResource errorTemplate}"
...
<TextBox Text="{Binding Value}" />
<TextBox Text="{Binding OtherValue}" />
My attached property automatically applies validation to every binding in the window, so the individual textboxes don't have to worry about validation.
To do this, I use this general techinique:
public class ValidationHelper : DependencyObject
{
[ThreadStatic]
static List<DependencyObject> _objectsNeedingValidationUpdate;
public static ControlTemplate GetErrorTemplate(DependencyObject obj) { return (ControlTemplate)obj.GetValue(ErrorTemplateProperty); }
public static void SetErrorTemplate(DependencyObject obj, ControlTemplate value) { obj.SetValue(ErrorTemplateProperty, value); }
public static readonly DependencyProperty ErrorTemplateProperty = DependencyProperty.RegisterAttached("ErrorTemplate", typeof(ControlTemplate), typeof(ValidationHelper), new FrameworkPropertyMetadata
{
Inherits = true,
PropertyChangedCallback = (obj, e) =>
{
if(e.NewValue)
if(_objectsNeedingValidationUpdate!=null)
_objectsNeedingValidationUpdate.Add(obj);
else
{
_objectsNeedingValidationUpdate = new List<DependencyObject>();
_objectsNeedingValidationUpdate.Add(obj);
Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Render, new Action(UpdateValidations));
}
},
});
static void UpdateValidations()
{
List<DependencyObject> objects = _objectsNeedingValidationUpdate;
_objectsNeedingValidationUpdate = null;
if(objects!=null)
foreach(DependencyObject obj in objects)
UpdateValidations(obj);
}
static void UpdateValidations(DependencyObject obj)
{
// My regular code uses obj.GetLocalValueEnumerator here, but that would require some other complexity
if(UpdateValidations(obj, TextBox.TextProperty))
if(Validation.GetErrorTemplate(obj)==null)
Validation.SetErrorTemplate(obj, ValidationHelper.GetErrorTemplate(obj));
}
static bool UpdateValidations(DependencyObject obj, DependencyProperty prop)
{
var binding = BindingOperations.GetBinding(obj, prop);
if(binding!=null &&
binding.Mode==BindingMode.TwoWay &&
!binding.ValidationRules.Any(rule => rule is ExceptionValidationRule))
{
binding.ValidationRules.Add(new ExceptionValidationRule());
BindingOperations.SetBinding(obj, prop, binding); // Required to get new rule to work
return true;
}
return false;
}
}
See the MSDN documentation of the Validation class for an example of how to create your errorTemplate resource. Also note that:
Take a look at binding validation. The Binding
class has a ValidationRules
collection, to which you can add an ExceptionValidationRule
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With