-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 12 posts ] 
Author Message
 Post subject: Basic databinding problem when dealing with NHibernate
PostPosted: Mon Mar 09, 2009 3:36 pm 
Newbie

Joined: Mon Mar 09, 2009 3:21 pm
Posts: 5
Hi, this problem extends past just NHibernate, its a general problem with databinding, but since it will come up constantly with NHibernate, I am wondering if anyone here knows how to deal with this.


How do you databind a DataGridViewComboBoxColumn?


For example, let's say you had a DataGridView and set its datasource as such:

dgv.DataSource = dataAcces.GetAll<Person>();

And let's say the "Person" class has a reference to a "MapLocation" as such:

public class Person
{
public virtual int Id { get; private set; }
public virtual string Name { get; set; }
public virtual MapLocation { get; set; }
}

And MapLocation is defined as:

public class MapLocation
{
public virtual int Id { get; private set; }
public virtual string MapName { get; set; }
}

Now suppose we add a DataGridViewComboBoxColumn to our "dgv" DataGridView:

dgv.Columns.Add(
new DataGridViewComboBoxColumn
{
HeaderText = "Map",
DataPropertyName = "MapLocation",
DataSource = dataAcces.GetAll<MapLocation>(),
DisplayMember = "MapLocationName",
//ValueMember = "MapLocation", // WHAT GOES HERE
DisplayStyleForCurrentCellOnly = true,
FillWeight = 1
});


How do you set up this databinding??

Ideally I would set up the comboboxcolumn with:

DataPropertyName = "MapLocation.Id"
DisplayMember = "MapLocationName"
ValueMember = "Id"

Except that "MapLocation.Id" is not possible.

So, how is this databinding accomplished? Thanks


Top
 Profile  
 
 Post subject:
PostPosted: Wed Mar 11, 2009 11:37 am 
Regular
Regular

Joined: Wed Feb 11, 2009 10:58 am
Posts: 55
I did something similar here:

Code:
public class Order
  {
    public virtual String OrderId { get; set; }
    protected virtual Location _location { get; set; }

    public static Dictionary<Decimal, Location> Locations;
    public static void InitLocations()
    {
      IList<Location> locations = NHibernateFactory.Session.CreateQuery("from Location").List<Location>();

      Locations = new Dictionary<decimal, Location>();
      foreach (Location l in locations)
        Locations.Add(l.LocationId, l);
    }

    public virtual Decimal location
    {
      get
      {
        return _location.LocationId;
      }
      set
      {
        _location = Locations[value];
      }
    }

  }


The DataGridViewColumn was set up like this:
Code:
//
      // locationDataGridViewTextBoxColumn
      //
      this.locationDataGridViewTextBoxColumn.DataPropertyName = "location";
      this.locationDataGridViewTextBoxColumn.DataSource = this.locationBindingSource;
      this.locationDataGridViewTextBoxColumn.DisplayMember = "Name";
      this.locationDataGridViewTextBoxColumn.HeaderText = "location";
      this.locationDataGridViewTextBoxColumn.Name = "locationDataGridViewTextBoxColumn";
      this.locationDataGridViewTextBoxColumn.Resizable = System.Windows.Forms.DataGridViewTriState.True;
      this.locationDataGridViewTextBoxColumn.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.Automatic;
      this.locationDataGridViewTextBoxColumn.ValueMember = "LocationId";


locationBindingSource is a BindingSource using the Location Class as DataSource.

So if you change the value in the ComboBox in the Grid the Property looks up the Location in the Dictionary and passes it back.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Mar 11, 2009 11:38 am 
Regular
Regular

Joined: Wed Feb 11, 2009 10:58 am
Posts: 55
I did something similar here:

Code:
public class Order
  {
    public virtual String OrderId { get; set; }
    protected virtual Location _location { get; set; }

    public static Dictionary<Decimal, Location> Locations;
    public static void InitLocations()
    {
      IList<Location> locations = NHibernateFactory.Session.CreateQuery("from Location").List<Location>();

      Locations = new Dictionary<decimal, Location>();
      foreach (Location l in locations)
        Locations.Add(l.LocationId, l);
    }

    public virtual Decimal location
    {
      get
      {
        return _location.LocationId;
      }
      set
      {
        _location = Locations[value];
      }
    }

  }


The DataGridViewColumn was set up like this:
Code:
//
      // locationDataGridViewTextBoxColumn
      //
      this.locationDataGridViewTextBoxColumn.DataPropertyName = "location";
      this.locationDataGridViewTextBoxColumn.DataSource = this.locationBindingSource;
      this.locationDataGridViewTextBoxColumn.DisplayMember = "Name";
      this.locationDataGridViewTextBoxColumn.HeaderText = "location";
      this.locationDataGridViewTextBoxColumn.Name = "locationDataGridViewTextBoxColumn";
      this.locationDataGridViewTextBoxColumn.Resizable = System.Windows.Forms.DataGridViewTriState.True;
      this.locationDataGridViewTextBoxColumn.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.Automatic;
      this.locationDataGridViewTextBoxColumn.ValueMember = "LocationId";


locationBindingSource is a BindingSource using the Location Class as DataSource.

So if you change the value in the ComboBox in the Grid the Property looks up the Location in the Dictionary and passes it back.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Mar 11, 2009 11:09 pm 
Newbie

Joined: Mon Mar 09, 2009 3:21 pm
Posts: 5
I thought the whole point of NHibernate (and Hibernate in general) was that you could map your database table models to POCOs (plain old C# objects).

No offense, but what you've written hardly looks like a plain old C# object anymore. It has a custom querying language embedded in it for chrissakes.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Mar 12, 2009 3:44 am 
Regular
Regular

Joined: Wed Feb 11, 2009 10:58 am
Posts: 55
Well... mapping an Object into a DataGridView column is simply not possible. So you have to tell the DataGridView which property to show and how they are connected.
That's nothing else for any other Lookup functionality. If you connect the DataGridView with a TableAdapter the MapLocation in your Table would be a int (or something similar) and not a complex class.
Maybe there's a more comfortable way to do such a mapping. I'm neither a CSharp Guru nor am I a NHibernate Guru.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Mar 12, 2009 4:34 pm 
Newbie

Joined: Mon Mar 09, 2009 3:21 pm
Posts: 5
I am neither as well :)

What I mean is, if NHibernate can't handle a fundamental thing like WinForms databinding in an elegant manner, maybe NHibernate sucks for a WinForms application. In fact it seems like that is the case, unless someone knows something I don't about how to do this easily.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Mar 13, 2009 4:11 am 
Expert
Expert

Joined: Thu Dec 14, 2006 5:57 am
Posts: 1185
Location: Zurich, Switzerland
Try DisplayMember = "Name" and no ValueMember, since your combobox datasource contains MAPLocation objects.

_________________
--Wolfgang


Top
 Profile  
 
 Post subject:
PostPosted: Fri Mar 13, 2009 5:53 am 
Regular
Regular

Joined: Wed Feb 11, 2009 10:58 am
Posts: 55
Did not work for me, though it was a really nice idea.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Mar 13, 2009 6:13 am 
Expert
Expert

Joined: Thu Dec 14, 2006 5:57 am
Posts: 1185
Location: Zurich, Switzerland
I meant DisplayMember="MapName", but you probably tried that. Have you implemented GetHashCode() and Equals() on MapLocation ? Since you most likely have different instances of MapLocation in the data-bound item and the combobox datasource, you have to make sure that the objects are considered equal when they have the same id !

Have a look here if you need more information:

http://nhforge.org/blogs/nhibernate/archive/2008/09/06/identity-field-equality-and-hash-code.aspx

You can start with implementing the standard overrides and set breakpoints and check what's happending during databinding. Additionally you can implement Format and Parse events on the grid and check the object types you're dealing with. It's always a hassle ...

_________________
--Wolfgang


Top
 Profile  
 
 Post subject:
PostPosted: Sat Mar 14, 2009 7:03 am 
Regular
Regular

Joined: Wed Feb 11, 2009 10:58 am
Posts: 55
That was my second thought, too. I tried to override the GetHashCode and Equals function, but that didn't help either.
But I don't think this is a NHibernate specific problem as it would happen for every Object containing another Object.
I've searched the Internet for binding objects to a GridViewComboBoxColumn, but didn't find any nice way to do it. I'll have a look at it, if I'm back at work :)


Top
 Profile  
 
 Post subject:
PostPosted: Tue Mar 17, 2009 4:53 pm 
Newbie

Joined: Mon Mar 09, 2009 3:21 pm
Posts: 5
I'm coming to the conclusion that you simply [i][b]can not databind effectively using ANY form of domain-driven design[/b][/i]!

It's simply not possible.

It's true that this is more of a fault of how databinding is handled in WinForms than an indictment against DDD in general.

However, the fact remains that these two things do not, in their current form, coexist.[/i]


Top
 Profile  
 
 Post subject:
PostPosted: Mon Mar 23, 2009 4:04 am 
Regular
Regular

Joined: Wed Feb 11, 2009 10:58 am
Posts: 55
if you need that very urgently there are several implementations of a DataGridViewComboBoxCell supporting Object binding in the Internet.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 12 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.