By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
432,414 Members | 1,057 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 432,414 IT Pros & Developers. It's quick & easy.

Databinding of complex business layer classes

P: n/a
Hello,

I have a problem to use databinding with my business layer classes. My
data class does not have simple properties (string, int or datetime),
instead, all my properties are objects of the generic type Field<T>
(see sample code).

public class Employee
{
public Field<stringForename
{
get
{
if(m_Forename == null)
m_Forename = new Field<string>(....);

return m_Forename;
}
}

public Field<stringLastname
{
get
{
if(m_Lastname == null)
m_Lastname= new Field<string>(....);

return m_Lastname;
}
}

// The Employee class has many more properties with the Field<T>
datatype.
}
public class Field<T>
{
public T CurrentValue
{
get
{
// Get Field from database...
return ...;
}
set
{
// Save Value in Database

// Save last change date.

// Save NT-Username of the User who made the last changes
}
}

public DateTime LastChangeDate
{
get
{
return ...;
}
}

public string LastChangeUserName
{
get
{
return ...;
}
}

// I have some more informations for each Field...
}

When I now try to use databinding of a collection of those objects to
da grid (I use the Janus GridEx, but the problem is a general
databinding problem), I have the problem that the databinding
expression only accepts one-level-property names "Forename". What I
need is something like "Forename.CurrentValue", but that is not
possible.

I know that it would be possible to add every Property in the Employee
class twice like

public string FornameValue
{
get
{
return this.Forname.CurrentValue;
}
}
But this is a ugly solution.

Does anyone have an idea how I can change the Field<Tclass so that I
can use it with Databinding?

Regards
Dirk

Jan 3 '07 #1
Share this Question
Share on Google+
8 Replies


P: n/a
"Dirk" <di********@gmail.coma écrit dans le message de news:
11*********************@s34g2000cwa.googlegroups.c om...

| I have a problem to use databinding with my business layer classes. My
| data class does not have simple properties (string, int or datetime),
| instead, all my properties are objects of the generic type Field<T>

Do not expose the Field<Tobjects as public properties. You really need to
create a base business class that is capable of holding a list of these
field objects and then access them the derived classes.

internal abstract class Field
{
private string name;

internal Field(string name)
{
this.name = name;
}

public string Name
{
get { return name; }
}
}

internal class Field<T: Field
{
private T value;

...

internal T Value
{
get { return ...; }
set { ... = value; }
}
}

public abstract class Base
{
private Dictionary<string, Fieldfields = new Dictionary<string,
Field>();

protected bool ContainsField(string fieldName)
{
return field.ContainsKey(fieldName);
}

protected void Add<T>(string fieldname)
{
fields[fieldname] = new Field<T>(fieldName);
}

protected T GetFieldValue<T>(string fieldName)
{
return fields[fieldName].Value;
}

protected void SetFieldValue<T>(string fieldName, T value)
{
fields[fieldName].Value = value;
}
}

public class Employee : Base
{
public string Forename
{
get
{
string fieldName = "Forename";

if (ContainsField(fieldName))
Add<string>(fieldName);

return GetFieldValue<string>(fieldName);
}
}

I have taken this one step further and used the idea of a Data Packet which
contains the list of fields and manages all sorts of other stuff under the
hood, but this should give you the general idea.

Joanna

--
Joanna Carter [TeamB]
Consultant Software Engineer
Jan 3 '07 #2

P: n/a
"Joanna Carter [TeamB]" <jo****@not.for.spama écrit dans le message de
news: eL*************@TK2MSFTNGP04.phx.gbl...

Sorry, I forgot the cast on the fields in the accessors.

| protected T GetFieldValue<T>(string fieldName)
| {
*** return ((Field<T>) fields[fieldName]).Value;
| }
|
| protected void SetFieldValue<T>(string fieldName, T value)
| {
*** ((Field<T>) fields[fieldName]).Value = value;
| }

Joanna

--
Joanna Carter [TeamB]
Consultant Software Engineer
Jan 3 '07 #3

P: n/a
Dirk wrote:
Hello,

I have a problem to use databinding with my business layer classes. My
data class does not have simple properties (string, int or datetime),
instead, all my properties are objects of the generic type Field<T>
(see sample code).

public class Employee
{
public Field<stringForename
{
get
{
if(m_Forename == null)
m_Forename = new Field<string>(....);

return m_Forename;
}
}

public Field<stringLastname
{
get
{
if(m_Lastname == null)
m_Lastname= new Field<string>(....);

return m_Lastname;
}
}

// The Employee class has many more properties with the Field<T>
datatype.
}
public class Field<T>
{
public T CurrentValue
{
get
{
// Get Field from database...
return ...;
}
set
{
// Save Value in Database

// Save last change date.

// Save NT-Username of the User who made the last changes
}
}

public DateTime LastChangeDate
{
get
{
return ...;
}
}

public string LastChangeUserName
{
get
{
return ...;
}
}

// I have some more informations for each Field...
}

When I now try to use databinding of a collection of those objects to
da grid (I use the Janus GridEx, but the problem is a general
databinding problem), I have the problem that the databinding
expression only accepts one-level-property names "Forename". What I
need is something like "Forename.CurrentValue", but that is not
possible.

I know that it would be possible to add every Property in the Employee
class twice like

public string FornameValue
{
get
{
return this.Forname.CurrentValue;
}
}
But this is a ugly solution.

Does anyone have an idea how I can change the Field<Tclass so that I
can use it with Databinding?

Regards
Dirk
I like your general idea and I am struggling with similar issue. I ran
into a very good article by Alexander Gornik "Making ASP.NET databinding
via # work, without reflection"
(http://www.codeproject.com/aspnet/TypeDescriptors.asp)
Hope this helps.
The solution by Joanna is very feasible but undesirable due to the
strange and complex databinding expression you may need to use.
I would like to see her post a working small example.
Regards,
intrader
Jan 4 '07 #4

P: n/a
Dirk wrote:
Hello,

I have a problem to use databinding with my business layer classes. My
data class does not have simple properties (string, int or datetime),
instead, all my properties are objects of the generic type Field<T>
(see sample code).

public class Employee
{
public Field<stringForename
{
get
{
if(m_Forename == null)
m_Forename = new Field<string>(....);

return m_Forename;
}
}

public Field<stringLastname
{
get
{
if(m_Lastname == null)
m_Lastname= new Field<string>(....);

return m_Lastname;
}
}

// The Employee class has many more properties with the Field<T>
datatype.
}
public class Field<T>
{
public T CurrentValue
{
get
{
// Get Field from database...
return ...;
}
set
{
// Save Value in Database

// Save last change date.

// Save NT-Username of the User who made the last changes
}
}

public DateTime LastChangeDate
{
get
{
return ...;
}
}

public string LastChangeUserName
{
get
{
return ...;
}
}

// I have some more informations for each Field...
}

When I now try to use databinding of a collection of those objects to
da grid (I use the Janus GridEx, but the problem is a general
databinding problem), I have the problem that the databinding
expression only accepts one-level-property names "Forename". What I
need is something like "Forename.CurrentValue", but that is not
possible.

I know that it would be possible to add every Property in the Employee
class twice like

public string FornameValue
{
get
{
return this.Forname.CurrentValue;
}
}
But this is a ugly solution.

Does anyone have an idea how I can change the Field<Tclass so that I
can use it with Databinding?

Regards
Dirk
I may be mistaken here, but I have seen the syntax Forename_CurrentValue
in the # syntax.
Jan 4 '07 #5

P: n/a
"intrader" <in******@aol.coma écrit dans le message de news:
45**********************@roadrunner.com...

| The solution by Joanna is very feasible but undesirable due to the
| strange and complex databinding expression you may need to use.
| I would like to see her post a working small example.

Far from being a strange and complex databinding, it couldn't be simpler.

{
List<Employeeemployees = GetEmployeeList(...);

myGrid.DataSource = employees;

...
}

If you need to bind individual controls to an Employee, then all you do is

{
Employee e = new Employee();

textBox1.DataBindings.Add("Text", e, "Forename");

...
}

Joanna

--
Joanna Carter [TeamB]
Consultant Software Engineer
Jan 4 '07 #6

P: n/a
Hello Joanna, Intrader

thank you for your help.

First I tried "Forname_CurrentValue", but it did not work. Then I
retried "Forname.CurrentValue" and I recognized that it work readonly,
editing a column with such an Binding expression doesnt seem to work?

I will now analyze which of the two solutions I will realize.

regards
Dirk

Jan 4 '07 #7

P: n/a
"Josh" <Jo**@discussions.microsoft.coma écrit dans le message de news:
E4**********************************@microsoft.com...

| I am new to generics and would like to undersatnd the code you posted. I
| cannot get it to compile howver (even with the code change in your
subsequent
| post). Can you post a complete code that will compile?

There really isn't that much that doesn't work; after all I wrote the code
in the newsreader :-)

This is checked to compile and run :

// base non-generic class because we can't have use Field<T>
// for different types in a Dictionary that will only hold one type
internal abstract class Field
{
private string name;

internal Field(string name)
{
this.name = name;
}

public string Name
{
get { return name; }
}
}

// this is the real generic Field<Tclass that will be instantiated and
held
// in the Dictionary<string, Fieldin our base business class
internal class Field<T: Field
{
private T value;

internal Field(string name) : base(name) { }

internal T Value
{
get { return value; }
set { this.value = value; }
}
}

public abstract class Base
{
private Dictionary<string, Fieldfields = new Dictionary<string,
Field>();

protected Base()
{
// get list of publicly declared properties in class derived from this
class
PropertyInfo[] properties = GetType().GetProperties();

foreach (PropertyInfo property in properties)
{
// bind Field<to the type of the property
Type fieldType =
typeof(Field<>).MakeGenericType(property.PropertyT ype);

// create an array to hold the constructor args
object[] args = new object[] { property.Name };

// use Activator to create the Field<Tinstance
Field newField = (Field) Activator.CreateInstance(fieldType,
BindingFlags.Instance | BindingFlags.NonPublic, null, args, null, null);

// add the field to the private list
fields.Add(property.Name, newField);
}
}

protected T GetFieldValue<T>(string fieldName)
{
return ((Field<T>) fields[fieldName]).Value;
}

protected void SetFieldValue<T>(string fieldName, T value)
{
((Field<T>) fields[fieldName]).Value = value;
}
}

public class Employee : Base
{
public Employee() : base() { }

public string Forename
{
get { return GetFieldValue<string>("Forename"); }
set { SetFieldValue<string>("Forename", value); }
}
}

Does that help ?

Joanna

--
Joanna Carter [TeamB]
Consultant Software Engineer
Jan 4 '07 #8

P: n/a
Joanna Carter [TeamB] wrote:
"intrader" <in******@aol.coma écrit dans le message de news:
45**********************@roadrunner.com...

| The solution by Joanna is very feasible but undesirable due to the
| strange and complex databinding expression you may need to use.
| I would like to see her post a working small example.

Far from being a strange and complex databinding, it couldn't be simpler.

{
List<Employeeemployees = GetEmployeeList(...);

myGrid.DataSource = employees;

...
}

If you need to bind individual controls to an Employee, then all you do is

{
Employee e = new Employee();

textBox1.DataBindings.Add("Text", e, "Forename");

...
}

Joanna
Sorry for the characterization.
What you have described is quite simple and elegant.
Jan 27 '07 #9

This discussion thread is closed

Replies have been disabled for this discussion.