This is second part of my article where I talk about Validation in WPF using Entlib Validation Application Block. First part of my article is located on this location : http://blog.developers.ba/post/2009/07/07/WPF-Validation-using-Validation-Application-Block-41-Part-1-e28093-Server-side.aspx

There are many articles about client side validation in WPF. Most of these articles are similar and use implementation of IDataErrorInfo interface on Model class.

I have use some methods  already described in other articles just to show you how easy it is to implement client side validation in WPF using VAB.

I have model class called Customer where I have implemented IDataErrorInfo. Code looks like this :

public string Error
{
get {
StringBuilder error = new StringBuilder();
ValidationResults results = Validation.ValidateFromAttributes(this);
foreach (ValidationResult result in results)
{
error.AppendLine(result.Message);
}
return error.ToString() ;
}
}
public string this[string columnName]
{
get {
ValidationResults results = Validation.ValidateFromAttributes(this);
foreach (ValidationResult result in results)
{
if (result.Key == columnName)
{
return result.Message;
}
}
return string.Empty;
}
}

I have called ValidateFromAttributes method of Validation class that exists in VAB to get collection of ValidationResults. It is easy as that.

In Application.Resources of my WPF application I have defined some textbox error template and style to use when validation error is occurred. For this I have borrowed some code from other articles to save on time writing templates and styles.

And final in xaml on textboxes I have added following code where I have turn on Validation and defined witch error template to use :

<TextBox x:Name="txtFirstName"  Grid.Column="1"  TextWrapping="Wrap" 
Text="{Binding FirstName, ValidatesOnDataErrors=True}" Validation.ErrorTemplate="{StaticResource TextBoxErrorTemplate}" />

References :

http://msdn.microsoft.com/en-us/magazine/cc700358.aspx

http://www.eggheadcafe.com/tutorials/aspnet/f726cd7d-cfcc-43c3-85d8-2afc75e7a08a/wpf-input-validation-with.aspx

Here is updated code in VS2010RC :ValidationServiceWCF.rar

Currently rated 5.0 by 2 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Screenshot your WPF application

Published 03.09.2009 06:17 AM by Admin in WPF
Tags: ,

Often we need a way to capture picture of UI. For example if error occurs in our application we can take picture of UI and send this picture in error report.

Usual way in windows forms is calling Graphic.CopyFromScreen method. This way is not work very well in WPF. If we have some transparent controls on form this method will save image under transparent control.

So in WPF we will use GDI+ to take picture of UI. We have internal class NativeMethods:

 internal class NativeMethods

    {

        [DllImport("user32.dll")]

        public extern static IntPtr GetDesktopWindow();

 

        [System.Runtime.InteropServices.DllImport("user32.dll")]

        public static extern IntPtr GetWindowDC(IntPtr hwnd);

 

        [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]

        public static extern IntPtr GetForegroundWindow();

 

        [System.Runtime.InteropServices.DllImport("gdi32.dll")]

        public static extern UInt64 BitBlt

             (IntPtr hDestDC,

             int x,

             int y,

             int nWidth,

             int nHeight,

             IntPtr hSrcDC,

             int xSrc,

             int ySrc,

             System.Int32 dwRop);

    }

And we take picture UI by calling this method :

 public void SaveScreen()

        {

            Bitmap myImage = new Bitmap(Screen.PrimaryScreen.WorkingArea.Width,

            Screen.PrimaryScreen.WorkingArea.Height);

 

            Graphics gr1 = Graphics.FromImage(myImage);

            IntPtr dc1 = gr1.GetHdc();

 

            IntPtr dc2 = NativeMethods.GetWindowDC(NativeMethods.GetForegroundWindow());

 

 

            NativeMethods.BitBlt(dc1, Screen.PrimaryScreen.Bounds.X, Screen.PrimaryScreen.Bounds.Y, Screen.PrimaryScreen.Bounds.Width,

                 Screen.PrimaryScreen.Bounds.Height, dc2, 0, 0, 13369376);

            gr1.ReleaseHdc(dc1);

            myImage.Save("screen.png", ImageFormat.Png);

        }

 

You can download Demo application :

ScreenShotWPF.rar (38.14 kb)

Currently rated 2.5 by 4 people

  • Currently 2.5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

If you are interesting to learn more about Validation Application Block you can always download Hand on Labs about VAB: http://www.microsoft.com/downloads/details.aspx?FamilyID=2C34A9CB-17CF-4AEC-8DE6-EEACBBB74413&displaylang=en

In these labs you will find very good explanation about using VAB integration with WCF, but what if you are manually creating proxy instead using add service reference?

In this article I will show you how to use VAB 4.1 with WCF and manually generated proxy.

My solution structure looks like this :

Picture1

I have created one project called DataContracts where all DataContract classes and Validation rules are defined. Code for that class looks like this :

 public class Customer

    {

        [StringLengthValidator(1, 25,

           MessageTemplateResourceType = typeof(Resources),

           MessageTemplateResourceName = "FirstNameMessage")]

        [NotNullValidator]

        public string FirstName { get; set; }

        [StringLengthValidator(1, 25,

          MessageTemplateResourceType = typeof(Resources),

          MessageTemplateResourceName = "LastNameMessage")]

        [NotNullValidator]

        public string LastName { get; set; }

        public string Nickname { get; set; }

        public DateTime BirthDate { get; set; }

        [ObjectValidator]

        public Address Address { get; set; }

 

        public Customer()

        {

            this.Address=new Address();

        }

    }

 

    public class Address

    {

        [StringLengthValidator(1, 50)]

        public string StreetName { get; set; }

 

        public int Number { get; set; }

        [DomainValidator("AL", "AK", "AS", "AZ", "AR", "CA", "CO", "CT", "DE", "DC", "FM", "FL", "GA", "GU", "HI", "ID", "IL", "IN", "IA", "KS", "KY", "LA", "ME", "MH", "MD", "MA", "MI", "MN", "MS", "MO", "MT", "NE", "NV", "NH", "NJ", "NM", "NY", "NC", "ND", "MP", "OH", "OK", "OR", "PW", "PA", "PR", "RI", "SC", "SD", "TN", "TX", "UT", "VT", "VI", "VA", "WA", "WV", "WI", "WY",

            MessageTemplate = "Value is not a valid US state two-letter abbreviation.")]

        public string USState { get; set; }

 

    }

I have manually created proxy class. It looks like this :

  public class CustomerClientProxy : ClientBase<ICustomerService>, ICustomerService

    {

 

        public string ProcessCustomer(DataContracts.Customer customer, string notes)

        {

            return Channel.ProcessCustomer(customer, notes);

        }

 

    }

In service contracts project I have defined interface that WCF will use. We must decorate method signature in interface with  validation attribute that define FaultContract for method.

We are using  ValidationFault class that is defined in VAB for error transporting to the client side.

  [FaultContract(typeof(ValidationFault))]

        string ProcessCustomer(

            Customer customer, [StringLengthValidator(1, 100,

                MessageTemplate = "The notes must be 1 to 100 characters long.")]

            string notes);

In web config file for WCF service we must add new behaviorConfiguration for Endpoint. ValidationElement is used to perform some validation actions on WCF before calling method on WCF.

<behaviorExtensions>
<add name="validation" type="Microsoft.Practices.EnterpriseLibrary.Validation.Integration.WCF.ValidationElement, 
        Microsoft.Practices.EnterpriseLibrary.Validation.Integration.WCF, Version=4.1.0.0, Culture=neutral, 
        PublicKeyToken=31bf3856ad364e35" />
</behaviorExtensions>

On client side I have one standard WPF application with basic App.Config where is just defined ABC for WCF. (address, binding, contract)

I have bind client side textboxes on the form with my Customer class.  After that I have some code to catch exceptions throw by the server and show that exceptions in simple message box.

using (Proxy.CustomerClientProxy client = new Proxy.CustomerClientProxy())

            {

                try

                {

 

                    Customer cust=((Customer)this.DataContext);

 

                    client.ProcessCustomer(cust, "My message!!!");

                }

                catch (FaultException<ValidationFault> fex)

                {

                    StringBuilder builder = new StringBuilder();

                    builder.AppendLine("Validation error invoking service:
"
);

                    foreach (ValidationDetail result in fex.Detail.Details)

                    {

                        builder.AppendLine(

                            string.Format("{0}: {1}
"
, result.Key, result.Message));

                    }

 

                    MessageBox.Show(builder.ToString());

 

                }

 

                catch (Exception ex)

                {

                    MessageBox.Show(ex.StackTrace.ToString());

                }

            }

After I run my application and enter some incorrect values I get message box :

Picture2

 

Here is complete code :ValidationServiceWCF.rar

Reference : http://www.clariusconsulting.net/blogs/kzu/archive/2007/09/24/WhyweneedanEntLibStandaloneValidationApplicationBlock.aspx

Currently rated 4.5 by 2 people

  • Currently 4.5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Radenko Zec Blog

Silverlight, C#, WCF, WPF,NET...