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 / August 2007

Tip: Looking for answers? Try searching our database.

DataBinding to array elements

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Douglas Harber - 09 Aug 2007 21:43 GMT
I've got a problem that I've been wracking my brain to try to come up with a
solution for. Basically, I've got either some XML or an object deserialized
from that XML which has elements that have more than one occurrence. So, for
instance, a fragment of the XML might look like this:

<Sender>
 <Name>Test Sender</Name>
 <Address>Address Line 1</Address>
 <Address>Address Line 2</Address>
 <Address>Address Line 3</Address>
</Sender>

This would get serialized into an object that looked something like this:

public class Sender
{
   private string name;
   private string[] address;

   public string Name
   {
       get { return name; }
       set { name = value; }
   }

   public string[] Address
   {
       get { return address; }
       set { address = value; }
   }
}

My problem is that I want to databind to either a DataSet that the XML has
been loaded into, or to the object that was deserialized from it. Binding to
the Name property is no problem. The Address represents a problem, though.
The form I want to bind data on has 3 textboxes for address lines, and I'd
like to bind each textbox to one of the address string in Address.

The first problem, of course, is that there may or may not be 3 entries in
Address but I'm willing to stipulate that the XML schema will have
minOccurs=3.

Which comes to the real problem. Is there anyway to databind to a specific
element within a collection? It doesn't matter whether it's in a DataSet or
an object. But I haven't found any way to do it yet. Unfortunately, this is
very common pattern in the data model of the application I'm trying to
reengineer, so I'm not going to have a lot of control over changing it.
Currently, the application implements methods on each form to load and save
the fields from and to an object, so each form has at least one
LoadFieldsFromXxx and SaveFieldsToXxx method, which is a terribly
unsatisfying way to implement them.

Any help or suggestions would be greatly appreciated.

Thanks,
Doug Harber
Marc Gravell - 10 Aug 2007 08:31 GMT
Do you control the class?

How about a simple shim through properties - i.e.

[XmlIgnore]
public string AddressLine1 { get {return Address[0];} set
{Address[0]=value;}}
[XmlIgnore]
public string AddressLine2 { get {return Address[1];} set
{Address[1]=value;}}

you can now databind to these, safe in the knowledge that they don't
affect serialization.

(you'd need error handling on the index etc)
Also - I don't recomment coding against an array - a
Collection<Address> or similar would be far more controlled:
private readonly Collection<Address> addresses = new
Collection<Address>();
[ some combination of XmlArray etc to get the naming right ]
public Collection<Address> AddressLines {get {return addresses;}}

(note then that your setter (for instance) could .Add if necessary)

I'll see if I can find the xml-markers for serialization of the above
(xsd.exe will be my first tool...)

Marc
Marc Gravell - 10 Aug 2007 09:14 GMT
like so (and I meant "string", not "Address"); note that I haven't
implemented notifications against AddressLine1 etc; this could be
done, but you'd need to work with a subclass of Collection<string>, or
switch to BindingList<string> (which also works), and handle the
insert/etc.

Marc

using System;
using System.Collections.ObjectModel;
using System.Xml.Serialization;
using System.ComponentModel;
using System.Collections.Generic;

class Program
{
   static void Main(string[] args)
   {
       Sender s = new Sender();
       s.Name = "Test Name";
       s.AddressLine3 = "Test 3";
       s.AddressLine1 = "Test 1";
       XmlSerializer ser = new XmlSerializer(typeof(Sender));
       ser.Serialize(Console.Out, s);
   }
}

[Serializable]
public sealed class Sender : INotifyPropertyChanged
{
   [XmlIgnore]
   public string AddressLine1 {
       get { return GetAddressLine(0); }
       set { SetAddressLine(0,value); }
   }
   [XmlIgnore]
   public string AddressLine2
   {
       get { return GetAddressLine(1); }
       set { SetAddressLine(1,value); }
   }
   [XmlIgnore]
   public string AddressLine3
   {
       get { return GetAddressLine(2); }
       set { SetAddressLine(2,value); }
   }
   public string GetAddressLine(int index)
   {
       return AddressLines.Count > index ? AddressLines[index] : "";
   }
   public void SetAddressLine(int index, string value)
   {
       while (AddressLines.Count <= index)
       {
           AddressLines.Add("");
       }
       AddressLines[index] = value;
   }

   string name;
   public string Name { get { return name; } set {SetField(ref name,
value, "Name");}}

   readonly Collection<string> addressLines = new
Collection<string>();
   [XmlElement("Address")]
   public Collection<string> AddressLines {get {return
addressLines;}}

   public event PropertyChangedEventHandler PropertyChanged;

   private void SetField<T>(ref T field, T value, string
propertyName) {
       if(EqualityComparer<T>.Default.Equals(field,value)) return; //
no change
       field = value;
       PropertyChangedEventHandler handler = PropertyChanged;
       if (handler != null) {
           handler(this, new PropertyChangedEventArgs(propertyName));
       }
   }
}
Tim Van Wassenhove - 15 Aug 2007 08:04 GMT
> Which comes to the real problem. Is there anyway to databind to a specific
> element within a collection? It doesn't matter whether it's in a DataSet or
> an object. But I haven't found any way to do it yet. Unfortunately, this is
> very common pattern in the data model of the application I'm trying to
> reengineer, so I'm not going to have a lot of control over changing it.

Instead of manually creating 'shim' properties, you could also implement
ICustomTypeDescriptor and expose each element via the GetProperties
implementation.

Signature

Kind regards,
Tim Van Wassenhove <url:http://www.timvw.be/>


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.