refer to forbox for suggested use

CONSORT 2010 Explanation and Elaboration: updated guidelines for reporting parallel group randomised trials | The BMJWelcome to upside
Hate Waiting for a Package? UPS My Choice is Here to&Help
| 09 / 14 / 2011
Getting a package delivered is fun. Waiting for it … well, not so much for most people. The drama of waiting was comically depicted by a
earlier this year. The video raised a few questions, .
Now we’re offering more than an answer … we’re offering a solution.
With UPS My Choicesm, you get the option to select an approximate delivery time for your packages. Won’t be at home? UPS My Choice lets you re-direct the package to another address … like your neighbor, vacation home or your local The UPS Store for a $5 fee per transaction.
Frequently shop online? Consider UPS My Choice Premium Membership. For an annual fee of $40, you can pick a two-hour delivery window for your shipment. Or provide detailed instructions for leaving the shipment … such as by the garage or porch. And re-directing packages to another address is free.
UPS My Choice launches October 3. You can register for the service starting today by visiting .
Want to learn more? Watch this video.
11/28/2011
We have a that answers the top questions shared with us from customers. The post also features a video that demonstrates how to use some of the most popular features, including how to change a delivery, setting alerts and providing delivery instructions.
, , , , , , ,
Related PostsRichard Ramdathsingh saw the accident unfold in front of his&For 31 years, The Conservation Fund has worked at the&By now you know the stats. The average age of&For many shoppers, buying auto parts bears little resemblance to&When I heard about the opportunity to plant trees at&WWF works to conserve nature and reduce the most pressing threats&
TRENDING TOPICS
We’re proud to share our latest
report! Thanks for following our efforts!
Thought you might like this:
Thanks for fighting alongside us for a more
Sharing this w/ our friends who are also passionate about . We’re pretty excited!
1 billion alternative fuel miles is a huge accomplishment! Here are our other
We’re aiming for more deliveries with less
impact. How do you think we’re doing?
We’re proud to share our latest
report! Thanks for following our efforts!
Thought you might like this:
Thanks for fighting alongside us for a more
Sharing this w/ our friends who are also passionate about . We’re pretty excited!
1 billion alternative fuel miles is a huge accomplishment! Here are our other
We’re aiming for more deliveries with less
impact. How do you think we’re doing?
UPSIDE ARCHIVES
Select Month
April 2016
August 2015
April 2015
February 2015
January 2015
December 2014
November 2014
September 2014
August 2014
March 2014
February 2014
January 2014
November 2013
October 2013
September 2013
August 2013
April 2013
March 2013
February 2013
January 2013
December 2012
November 2012
October 2012
September 2012
August 2012
April 2012
March 2012
February 2012
January 2012
December 2011
November 2011
October 2011
September 2011
August 2011
April 2011
March 2011
February 2011
January 2011
December 2010
November 2010
October 2010
September 2010
August 2010
April 2010
March 2010
February 2010
January 2010
December 2009
November 2009
Follow &upside Blog&
Get every new post delivered to your Inbox.
Join 143 other followersValidation in Windows Presentation Foundation - CodeProject
Sign in using
632.4K views16K downloads249 bookmarked
&4.87 (130 votes)
4.87/5 - 130 votes5 removedμ 4.82, σa 0.92 []
Rate this:
Introduction
Since the dawn of software development, the single biggest threat to reliable information has been end-users. After decades of the existence of computers, why do we still need to inform users that "the Start Date should always be less than the End Date", or that "First Name is a required field"? Since User.Current.Electrocute() won't be added to the .NET Framework until .NET 4.0, most of us generally have to resort to displaying some kind of UI cues to politely tell the user what they've done wrong, and how they can fix it.
Under Windows Forms, we had the ErrorProvider, and under ASP.NET, we had Validator controls. In Windows Presentation Foundation, the approach is going to change, but the goal remains the same: telling users that something is wrong. In this article, I'll discuss how input validation is designed to be handled in Windows Presentation Foundation (hereafter referred to as WPF). Specifically, I'll discuss the ExceptionValidationRule class, creating custom ValidationRules, how to display errors, when to display errors (UpdateSourceTriggers), and finally, an alternative approach using an implementation of the Windows Forms ErrorProvider for WPF.
Table of Contents
Welcome to WPF Validation
If you never spent much time with Windows Forms or data binding, I'm hoping that this article will remain simple enough to follow along. Validation in Windows Presentation Foundation takes an approach very similar to ASP.NET validation, in that most "business rules" are enforced on the user interface and applied to specific controls and bindings. This approach is quite simple to understand and implement, but some proponents of "rich domain models" and object-oriented designs (including myself) have some problems with it. As we approach the end of the article, I'll discuss why this is and a way to do things differently, but still leveraging some of the strengths of WPF.
On the other hand, if you did spend a lot of time using Windows Forms, and made heavy use of the ErrorProvider/IDataErrorInfo approach to validation, you might be disheartened to know that there isn't one in Windows Presentation Foundation. Luckily, since I too was disappointed about having to enforce everything "on the UI", towards the end of the article, I'll show how to create an ErrorProvider for use in your Windows Presentation Foundation applications. However, even if you're convinced that validating on the UI is a Bad Idea (TM), I'd encourage you to read the full article as I'll discuss some of the other validation features in WPF that you can still leverage.
Warning: All of the sample code was written using the BETA 2 release of .NET 3.0, and subsequently, some of it may have changed. Hopefully, the concepts will stay the same though, otherwise this will be a very wasted article
Very Simple Validation: ExceptionValidationRule
Most of the time when we talk about validation, we're talking about validating user input (other kinds of validation are outside the scope of this article). Let's look at the most simple kind of built-in validation offered by WPF - the ExceptionValidationRule. To begin our example, let's create a simple Customer class:public class Customer
private string _
public string Name
get { return _ }
set { _name = value; }
Writing classes is fun, but you'll probably never convince people to pay you unless you can add some kind of UI to let them interact with your classes. Since this article is about Windows Presentation Foundation, let's use XAML to create our UI. As we're smart developers, we'll also use data binding:&TextBox Text="{Binding Path=Name}" /&
Before we go any further, it's important to note that the odd-looking markup above is actually just a kind of shorthand for writing this:&TextBox&
&TextBox.Text&
&Binding Path="Name" /&
&/TextBox.Text&
&/TextBox&
Now, let's say one of your requirements is that customer names are mandatory. To implement this constraint, you could change your customer's Name property to look like this:public string Name
get { return _ }
_name = value;
if (String.IsNullOrEmpty(value))
throw new ApplicationException("Customer name is mandatory.");
Using WPF Validation Rules on our data binding, we can display this error automatically. All we need to do is make use of the ValidationRules property on our binding, like this:&TextBox&
&TextBox.Text&
&Binding Path="Name"&
&Binding.ValidationRules&
&ExceptionValidationRule /&
&/Binding.ValidationRules&
&/Binding&
&/TextBox.Text&
&/TextBox&
If you ran this code, you'd see something which looks like this:
Displaying Errors
Windows Presentation Foundation has a static class inside the System.Windows.Controls namespace, imaginatively named "". It has a number of static dependency properties which you can apply to any control. The ones we're most interested in are:
Errors - A list of error messages that apply to the bindings on this control.
HasError - Indicates whether there are any errors in the Errors property.
ErrorTemplate - A ControlTemplate we can apply if there is an error.
By default, the Validation class uses an ErrorTemplate that has a red border around the control, which is why we get a red border in the program above. If the default red borders aren't your thing, I'll understand. You might want thick green borders with orange exclamation marks:
To achieve the look you're after, you could define your own control template:&Application.Resources&
&ControlTemplate x:Key="TextBoxErrorTemplate"&
&DockPanel LastChildFill="True"&
&TextBlock DockPanel.Dock="Right"
Foreground="Orange"
FontSize="12pt"&!!!!&/TextBlock&
&Border BorderBrush="Green" BorderThickness="1"&
&AdornedElementPlaceholder /&
&/DockPanel&
&/ControlTemplate&
&/Application.Resources&
The AdornerElementPlaceholder is used to say "put the invalid control here". Once you've created this template, you can then reuse it on your customer name TextBox by setting the Validation.ErrorTemplate attached property:&TextBox
Validation.ErrorTemplate="{StaticResource TextBoxErrorTemplate}"&
Or, to save having to set the ErrorTemplate every time, you could do it in a WPF Style. If we were to set the style's TargetType to TextBox, and don't use a key, all text boxes in our application will automatically receive this style:&Style TargetType="{x:Type TextBox}"&
&Setter Property="Validation.ErrorTemplate"&
&Setter.Value&
&ControlTemplate&
&DockPanel LastChildFill="True"&
&TextBlock DockPanel.Dock="Right"
Foreground="Orange"
FontSize="12pt"&
&/TextBlock&
&Border BorderBrush="Green" BorderThickness="1"&
&AdornedElementPlaceholder /&
&/DockPanel&
&/ControlTemplate&
&/Setter.Value&
Now, green borders are all well and good, but they don't exactly tell the users what they've done wrong. Since we included the error message in the exception we were throwing earlier, we can make use of the static Validation.Errors attached property to get this value and use it as a property on our TextBox. The most common example is to set the ToolTip, like so:&Style TargetType="{x:Type TextBox}"&
[... SNIP: The code from above ...]
&Style.Triggers&
&Trigger Property="Validation.HasError" Value="true"&
&Setter Property="ToolTip"
Value="{Binding RelativeSource={RelativeSource Self},
Path=(Validation.Errors)[0].ErrorContent}"/&
&/Trigger&
&/Style.Triggers&
Now, if we mouse over the TextBox while it's in an error state, we'll get a tool-tip telling us what we did wrong:
All we need to do is place that style in our application resources, ensure we apply any validation rules to our bindings, and voila!
On a more advanced note, if you would rather show the errors somewhere else than in the ToolTip, such as in the TextBlock where the orange exclamation marks were, you could use a style like this:&Style TargetType="{x:Type TextBox}"&
&Setter Property="Validation.ErrorTemplate"&
&Setter.Value&
&ControlTemplate&
&DockPanel LastChildFill="True"&
&TextBlock DockPanel.Dock="Right"
Foreground="Orange"
FontSize="12pt"
Text="{Binding ElementName=MyAdorner,
Path=AdornedElement.(Validation.Errors)
[0].ErrorContent}"&
&/TextBlock&
&Border BorderBrush="Green" BorderThickness="1"&
&AdornedElementPlaceholder Name="MyAdorner" /&
&/DockPanel&
&/ControlTemplate&
&/Setter.Value&
Customized Validation Rules
I know what you're thinking: "Do I have to throw exceptions?"
I'm glad you asked. If you remember our customer's Name property above, you'll remember we were throwing an exception in order to display the errors using an ExceptionValidationRule. I'm sure most people will agree that throwing exceptions isn't really the optimal way of signaling that we have user input errors. Apart from the performance penalties, personally, I believe that "user input" errors aren't exactly "exceptional", and so they are not exactly what exceptions were designed for.
If you hunt around the framework, you'll see that the ExceptionValidationRule class inherits from an abstract ValidationRule class. The ValidationRule class looks like this:public abstract class ValidationRule
public abstract ValidationResult Validate(
object value,
CultureInfo culture);
When we created our binding earlier, I had some XAML that resembled this:&Binding Path="Name"&
&Binding.ValidationRules&
&ExceptionValidationRule /&
&/Binding.ValidationRules&
&/Binding&
The truth is, we could have used anything that inherits from the ValidationRule base class. Let's create a custom ValidationRule designed just to validate the lengths of strings.namespace MyValidators
public class StringRangeValidationRule : ValidationRule
private int _minimumLength = -1;
private int _maximumLength = -1;
private string _errorM
public int MinimumLength
get { return _minimumL }
set { _minimumLength = value; }
public int MaximumLength
get { return _maximumL }
set { _maximumLength = value; }
public string ErrorMessage
get { return _errorM }
set { _errorMessage = value; }
public override ValidationResult Validate(object value,
CultureInfo cultureInfo)
ValidationResult result = new ValidationResult(true, null);
string inputString = (value ?? string.Empty).ToString();
if (inputString.Length & this.MinimumLength ||
(this.MaximumLength & 0 &&
inputString.Length & this.MaximumLength))
result = new ValidationResult(false, this.ErrorMessage);
Our validator has three properties: a MinimumLength, a MaximumLength, and an ErrorMessage string which is shown if the value doesn't fit within the range. We're now ready to use it in our XAML.
First, we'll need to reference it in our XML namespaces at the top of the file:&Window [...]
xmlns:validators="clr-namespace:MyValidators" /&
Now we can add it to our binding's ValidationRules:&Binding Path="Name"&
&Binding.ValidationRules&
&validators:StringRangeValidationRule
MinimumLength="1"
ErrorMessage="A name is required." /&
&/Binding.ValidationRules&
&/Binding&
If you've added the styles I gave above, that should be all you need to do to show validation messages.
Controlling When to Validate: UpdateSourceTriggers
If you ran any of the sample code above, you'll notice that the validation only takes place when you hit Tab or click away from the text box. That's a good default for most cases, but if you'd like validation to take place at other times, you can use the UpdateSourceTrigger property on your binding.
The UpdateSourceTrigger property can take one of three possible values:
The default is LostFocus, which means that the bound data source will be updated and validated when the UI element loses focus (such as when you tab away, or click on another element).
The second option is PropertyChanged, which occurs when the property you are binding to (the TextBox's Text property in the example above) is changed. This enables you to validate whenever the user types or changes the value, without having to wait until they tab away (this is great for filtering a list of things).
Finally, there's the Explicit option, which only happens when you tell it to happen.
To make use of the UpdateSourceTrigger property in our code, all we'd need to do is set it in our binding:&TextBox&
&TextBox.Text&
&Binding Path="Name" UpdateSourceTrigger="PropertyChanged"&
&Binding.ValidationRules&
&ExceptionValidationRule /&
&/Binding.ValidationRules&
&/Binding&
&/TextBox.Text&
&/TextBox&
For more information on UpdateSourceTriggers, see the .
Where Does an ErrorProvider Fit in?
We've already discussed that the ExceptionValidationRule isn't a nice way of validating. Some of the problems you may have with creating custom validation rules as I showed above are:
Our business "rules" are defined in markup, hidden inside our bindings, and can be hard to locate and maintain, as well as difficult to reuse.
We can't easily get a "list" of all of the broken rules on a form in order to perform other logic - such as determining if the customer can be saved when the "Save" button is clicked.
Defining business rules in markup may not be such a problem for some applications, but in applications with rich business objects such as , or applications using rich frameworks such as , or in cases where the rules are shared across many screens or applications, you may find this to be a big limitation. If this isn't a problem for you, you might not get much out of the rest of this article.
This means that the ValidationRules approach isn't very useful to some of us. However, all is not lost, as we can still make use of the static Validation class, and of its use of styles and control templates to control the display of errors.
IDataErrorInfo
The IDataErrorInfo interface has been kicking around since .NET 1.1, and was used heavily in DataSets as well as used by many business object frameworks. You'll find this gem in the <ponentModel namespace. If you've been reading
for some time, hopefully this interface isn't a stranger to you.
IDataErrorInfo was designed for reporting errors to user interface controls from the objects they are bound to. The DataGrid (1.1) and DataGridView (2.0) in Windows Forms both detected the presence of this interface on objects they were bound to automatically, and showed any errors without any work. The Windows Forms ErrorProvider could automatically be used to display errors on any control that came from the objects they (and the ErrorProvider) were bound to, all without any extra code being written.
To refresh your memory, this is how we would have used this interface in .NET 2.0:public class Customer : IDataErrorInfo
private string _
public string Name
get { return _ }
set { _name = value; }
public string Error
return this[string.Empty];
public string this[string propertyName]
string result = string.E
propertyName = propertyName ?? string.E
if (propertyName == string.Empty || propertyName == "Name")
if (string.IsNullOrEmpty(this.Name))
result = "Name cannot be blank!";
Back then, all we had to do was bind a grid to our Customer object, and any errors would be automatically reported. If we bound the Customer's Name to a TextBox, we just had to drag an ErrorProvider onto the form, set its DataSource to our Customer object, and all of our validation was done for us.
Sadly, IDataErrorInfo appears to have been benched in WPF, as there doesn't seem to be any built-in support for it. This means that there is no ErrorProvider component in WPF either. Since the concept of an ErrorProvider is pretty simple, let's have a go at making one ourselves.
More on IDataErrorInfo...
is a good starting point. For a deeper discussion of the IDataErrorInfo interface and a better way to implement business object validation, you might enjoy my recent
article on the CodeProject. ' brilliant
also makes extensive use of the IDataErrorInfo interface.
Creating our ErrorProvider
The ErrorProvider that I have built (found in the attached sample code) inherits from the WPF Decorator class, which means you can "put stuff inside it". To use it, you just need to do something like this:&validators:ErrorProvider&
&StackPanel&
&TextBox Text="{Binding Path=Name}" /&
&TextBox Text="{Binding Path=Age}" /&
&/StackPanel&
&/validators:ErrorProvider&
My ErrorProvider works by cycling through all of the controls that are inside of it, and looking for any data bindings on their properties. When a value of one of the bound properties changes, it checks if its DataContext implements IDataErrorInfo, and if so, it gets any error messages, and displays them using the built-in static Validation class. That means you can use the styles and control templates that I showed above, whilst keeping all of your validation logic in another class.
Cycling through the control hierarchy in WPF is done using the
class. The code itself is a little long to post here, but is included in the sample code download at the top of the page.
Using the WPF ErrorProvider brings a number of benefits:
Your XAML is much more compact, as you don't need to add a list of ValidationRules to each binding.
All of your validation can be done by your business objects, rather than at the UI. This lets you have great encapsulation on your objects while still having an informative UI.
You can call the Validate() method on the ErrorProvider to force validation, and check if the controls are valid, rather than having to inspect each one.
You can use the GetFirstInvalidElement() method to get the first control with an error on your form, to set focus to it easily. This is great if, for example, your "Save" button has been clicked but you want to show them that they still have errors.
Conclusion
Whether you choose to use custom ValidationRules, my ErrorProvider, or simply throw exceptions, I hope I have given you enough information to make an educated decision that suits your project.
If your applications have a very rich domain model, you may find the ErrorProvider approach helpful. If your application is very service oriented, or very UI centric, ValidationRules might be all you need.
Of course, if none of these approaches suit your requirements, you could always hold out for .NET 4.0 and the introduction of User.Current.Electrocute()
Special Thanks
I would like to give a special thanks to Paul Czywcynski of
who has done a lot of testing with my ErrorProvider and given me a couple of bug fixes to make it work in a few places that I hadn't tried.
I'd also like to thank , who pointed me to the LogicalTreeHelper and also pointed me to ValidationRules (of course, he didn't mention them until after I'd done my ErrorProvider
This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.A list of licenses authors might use can be found
Octopus Deploy
My name is . I live in Brisbane and develop an automated release management product, . Prior to working on Octopus I worked for an investment bank in London, and for . I also work on . I am a Microsoft MVP for Client Application Development.
Comments and Discussions
General &&
Suggestion &&
Question &&
Admin && Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.
Last Updated 20 Aug 2006
Article Copyright 2006 by Paul StovellEverything else
Copyright & ,}

我要回帖

更多关于 for you refer 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信