C # DataGridView Binding Objects

I have a DataGridView and a list of objects that I would like to show.

The objects are as follows:

public class Entity { public int ID { get; set; } } public class Travel: Entity { public Service Service { get; set; } public City Source { get; set; } public City Destiny { get; set; } public decimal Price { get; set; } } public class Service: Entity { public string Name { get; set; } } public class City: Entity { public string Name { get; set; } // Max 50 chars } 

In my form, I am linking a list of Travel objects, like this:

 List<Travel> travels = logic.GetAllTravels(); DgvRecorridos.DataSource = travels; 

And I get the following:

enter image description here

I would like to receive the name of the service, the source and the city of fate.

Thanks in advance.

+1
source share
4 answers
 List<Travel> travels = logic.GetAllTravels(); var _bind = from a in travels select new { Servicename = a.Service.Name, SourceName = a.Source.Name, DestinyName = a.Destiny.Name, Price = a.Price }; DgvRecorridos.DataSource = _bind; 

or

 List<Travel> travels = logic.GetAllTravels(); var _bind = travels.Select(a => new { Servicename = a.Service.Name, SourceName = a.Source.Name, DestinyName = a.Destiny.Name, Price = a.Price }); DgvRecorridos.DataSource = _bind; 
+2
source

Instead of the following codes below:

 List<Travel> travels = logic.GetAllTravels(); DgvRecorridos.DataSource = travels; 

Do it:

 List<Travel> travels = logic.GetAllTravels(); BindingSource bs = new BindingSource(); bs.DataSource = travels; DgvRecorridos.AutoGenerateColumn = false; DgvRecorridos.DataSource = bs; 

Then add the columns manually:

 DataGridViewColumn col1 = new DataGridViewTextBoxColumn(); col1.DataPropertyName = "Service.Name"; col1.HeaderText = "Service Name"; dataGridView1.Columns.Add(col1); DataGridViewColumn col2 = new DataGridViewTextBoxColumn(); col2.DataPropertyName = "City.Name"; col2.HeaderText = "City Name"; dataGridView1.Columns.Add(col2); DataGridViewColumn col3 = new DataGridViewTextBoxColumn(); col3.DataPropertyName = "City.Name"; col3.HeaderText = "Destiny Name"; dataGridView1.Columns.Add(col3); DataGridViewColumn col4 = new DataGridViewTextBoxColumn(); col4.DataPropertyName = "Price"; col4.HeaderText = "Price"; dataGridView1.Columns.Add(col4); 

Then add a cell formatting event handler for the DataGridView:

 private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e) { if (dataGridView1.Rows[e.RowIndex].DataBoundItem != null && dataGridView1.Columns[e.ColumnIndex].DataPropertyName.Contains(".")) { e.Value = BindProperty(dataGridView1.Rows[e.RowIndex].DataBoundItem, dataGridView1.Columns[e.ColumnIndex].DataPropertyName); } } private string BindProperty(object property, string propertyName) { string retValue = ""; if (propertyName.Contains(".")) { PropertyInfo[] arrayProperties; string leftPropertyName; leftPropertyName = propertyName.Substring(0, propertyName.IndexOf(".")); arrayProperties = property.GetType().GetProperties(); foreach (PropertyInfo propertyInfo in arrayProperties) { if (propertyInfo.Name == leftPropertyName) { retValue = BindProperty(propertyInfo.GetValue(property, null), propertyName.Substring(propertyName.IndexOf(".") + 1)); break; } } } else { Type propertyType; PropertyInfo propertyInfo; propertyType = property.GetType(); propertyInfo = propertyType.GetProperty(propertyName); retValue = propertyInfo.GetValue(property, null).ToString(); } return retValue; } 

For a complete guide on cell formatting, check out Antonio Bello's blog post here , where I got the idea. ^ _ ^ I also asked here about the same question two days ago and received the same answers as you, and I know that this is not what you also want to do. Hope this helps you.

+2
source

Your design is so weird. I have a different approach - override the ToString() method of your classes (Service and City) as follows:

 public class Service: Entity { public string Name { get; set; } public override string ToString(){ return Name; } } public class City: Entity { public string Name { get; set; } // Max 50 chars public override string ToString(){ return Name; } } 

And it works fine. Again, your design is a bit weird ^ _ ^

0
source

All this code in the CellFormatting and BindProperty methods seems excessive. I mean, something basically did it, but I think it's already done. I implement INotifyPropertyChanged in the object that I want to snap to the grid line, and I put these objects in a BindingList. The BindingList is directly used as a data source for the grid.

This approach means a bit more typing in the base entity class that you map to the grid row, but I think it saves a lot more elsewhere. To implement INotifyPropertyChanged in your class:

 public class Entity: INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; public Entity() { Selected = false; } private bool _selected; public bool Selected { get { return _selected; } set { if (_selected != value) { _selected = value; OnPropertyChanged(nameof(Selected)); } } } protected virtual void OnPropertyChanged(string propertyName) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } } 

Then put the column in your grid and give it the name DataPropertyName "Selected" to match the name of the property in the Entity that should appear in that column. Obviously, add all the properties that you want to use in your grid, corresponding to the properties of the object. The key is to implement a property setting tool with a call to PropertyChanged.

This gives you a two-way snap between the grid and your list of objects.

My personal opinion: even this is too much code. I constantly find myself things that do the obvious: take a property by name and match it with something else that the name knows (for example, the grid column in this example). This is simply beyond my understanding of why these things are not just automatically connecting. The list and the grid should make sense enough to define this basic schema yourself. zero lines of code. Ok, one line of code. Grid.Datasource = List. So this is how I do it. I would like to know fewer code paths to do this.

0
source

Source: https://habr.com/ru/post/1347076/


All Articles