Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / Windows Forms / WinForm Data Binding / March 2008

Tip: Looking for answers? Try searching our database.

Databinding format in Business Object Layer

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Jerod Houghtelling - 04 Mar 2008 15:05 GMT
Hi all,

I would like to place a textbox on a form and have it bound to a
custom business object. What would be the recommended practice on
formatting and validating? My current implementation shown below works
for formatting the value in the business object, but the formatting is
not shown in the text box.

public class OrderHeader
{
   private string mOrderNumber;
   ...

   public string OrderNumber
   {
       get { return mOrderNumber; }
       set { mOrderNumber = value.Trim().ToUpper().PadLeft( 8,
'0' ); }
   }
}

txtOrderNumber.Databinding.Add( "Text", mOrderHeader, "OrderNumber",
true );

I've tried doing a INotifyPropertyChanged implementation, but the
textbox doesn't seem to be receiveing the PropertyChanged event, I'm
guessing because it knows that the property just changed so it is just
ingnoring it. I figure that I'll have to use some of the textbox
events but any help would be appriciated.

Thanks,
Jerod
Marc Gravell - 04 Mar 2008 15:39 GMT
Works fine for me... (with INotifyPropertyChanged implementation)

??

Marc

public class OrderHeader : INotifyPropertyChanged
{
   public event PropertyChangedEventHandler PropertyChanged;
   private string mOrderNumber;
   private void UpdateField<T>(ref T field, T value, string propertyName)
   {
       if (!EqualityComparer<T>.Default.Equals(field, value))
       {
           field = value;
           if (PropertyChanged != null)
           {
               PropertyChanged(this, new
PropertyChangedEventArgs(propertyName));
           }
       }
   }
   public string OrderNumber
   {
       get { return mOrderNumber; }
       set
       {
           string fmt = value.Trim().ToUpper().PadLeft(8, '0');
           UpdateField(ref mOrderNumber, fmt, "OrderNumber");
       }
   }
}

static class Program
{
   static void Main()
   {
       OrderHeader order = new OrderHeader();
       Application.EnableVisualStyles();
       using(Form f = new Form())
       using (TextBox tb1 = new TextBox())
       using (TextBox tb2 = new TextBox())
       {
           tb1.Dock = tb2.Dock = DockStyle.Top;
           tb1.DataBindings.Add("Text", order, "OrderNumber");
           tb2.DataBindings.Add("Text", order, "OrderNumber");
           f.Controls.Add(tb1);
           f.Controls.Add(tb2);
           Application.Run(f);
       }
   }
}
Jerod Houghtelling - 04 Mar 2008 16:35 GMT
> Works fine for me... (with INotifyPropertyChanged implementation)
>
[quoted text clipped - 52 lines]
>
> - Show quoted text -

Marc,

Thanks for your quick response. After testing your version everything
did work. I noticed that the difference was that I was setting the
fourth parameter on the textbox1.DataBindings.Add to true. When I
removed that parameter I was hitting an FormatException which was
thrown durring the load because my order number was null.

Any suggestions on where I should put the validating? I would like to
keep it in the business object so code doesn't have to be duplicated
in multiple forms.

Thanks again,
Jerod
Marc Gravell - 04 Mar 2008 20:26 GMT
> I would like to keep it in the business object so code doesn't
> have to be duplicated in multiple forms.
Absolutely; this is good practice - it separates the model from the
UI.

If you want the validation to *prevent* invalid entry, then put it in
the setter and raise an exception. If you want it to /notify/ the user
about data errors without interrupting the flow, then implement
IDataErrorInfo. Some UI controls (most notably DataGridView) support
this automatically, but for others you might need to cobble some
things together, perhaps involving an ErrorProvider. For a hasty, not
very pretty example - see below.

using System;
using System.Windows.Forms;
using System.ComponentModel;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
public class OrderHeader : INotifyPropertyChanged, IDataErrorInfo
{
   public event PropertyChangedEventHandler PropertyChanged;
   private string mOrderNumber;
   private void UpdateField<T>(ref T field, T value, string
propertyName)
   {
       if (!EqualityComparer<T>.Default.Equals(field, value))
       {
           field = value;
           if (PropertyChanged != null)
           {
               PropertyChanged(this, new
PropertyChangedEventArgs(propertyName));
           }
       }
   }
   public string OrderNumber
   {
       get { return mOrderNumber; }
       set
       {
           string fmt = value.Trim().ToUpper().PadLeft(8, '0');
           UpdateField(ref mOrderNumber, fmt, "OrderNumber");
       }
   }

   #region IDataErrorInfo Members

   static string GetAllErrors(IDataErrorInfo component)
   {
       StringBuilder sb = new StringBuilder();
       foreach (PropertyDescriptor property in
TypeDescriptor.GetProperties(component))
       {
           string propErr = component[property.Name];
           if (!string.IsNullOrEmpty(propErr))
           {
               sb.AppendLine(propErr);
           }
       }
       return sb.ToString();
   }

   string IDataErrorInfo.this[string columnName]
   {
       get {
           switch (columnName)
           {
               case "OrderNumber":
                   int len = mOrderNumber == null ? 0 :
mOrderNumber.Length;
                   if (len < 2 || len > 8){
                       return "Order number must be between 2 and 8
characters";
                   }
                   break;
           }
           return "";
       }
   }
   string IDataErrorInfo.Error
   {
       get { return GetAllErrors(this); }
   }

   #endregion
}

static class Program
{
   static void Main()
   {
       Application.EnableVisualStyles();
       OrderHeader order = new OrderHeader();
       order.OrderNumber = "0001";
       BindingList<OrderHeader> orders = new
BindingList<OrderHeader>();
       orders.Add(order);
       orders.AllowNew = orders.AllowRemove = false;
       using (Form f = new Form())
       using (TextBox tb1 = new TextBox())
       using (TextBox tb2 = new TextBox())
       using (DataGridView dgv = new DataGridView())
       using (ErrorProvider err = new ErrorProvider())
       {
           err.Icon = SystemIcons.Error;
           tb1.Top = 20;
           tb2.Top = 60;
           tb1.DataBindings.Add("Text", orders, "OrderNumber");
           tb2.DataBindings.Add("Text", orders,
"OrderNumber");
           order.PropertyChanged += delegate
           {
               err.SetError(tb2, ((IDataErrorInfo)order)
["OrderNumber"]);
           };
           dgv.DataSource = orders;
           dgv.Dock = DockStyle.Bottom;
           f.Controls.Add(tb1);
           f.Controls.Add(tb2);
           f.Controls.Add(dgv);
           Application.Run(f);
       }
   }
}

Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.