Binding objects DataGridView C#

前端 未结 4 492
南旧
南旧 2020-12-10 08:54

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

The Objects are these:

public class Entity
{
    public int ID { get; set; }
}         


        
相关标签:
4条回答
  • 2020-12-10 09:26
    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;
    
    0 讨论(0)
  • 2020-12-10 09:31

    All that code in the CellFormatting and BindProperty methods seems excessive. I mean, something's got to basically do that, but I think it's already been done. I implement INotifyPropertyChanged in the object I want to bind to a grid row, and I put those objects into a BindingList. The BindingList is directly used as the datasource for the grid.

    This approach means a little more typing in the basic entity class you're mapping 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 a column in your grid and give it a DataPropertyName of "Selected" to match the name of the property in Entity that should appear in that column. Obviously add whatever properties you want to your grid, matching the properties of the entity. The key is to be sure to implement the property setter with the call to PropertyChanged.

    This gets you two-way binding between the grid and your list of objects.

    My personal opinion: even this is way too much code. I find myself constantly writing these kinds of things that do the obvious: take a property by name and map it to something else that knows that name (like the grid column in this example). It's just beyond my comprehension why these things don't just automatically hook up. A list and grid should have enough sense to figure this basic arrangement on their own. zero lines of code. Ok, one line of code. Grid.Datasource = List. So this is how I do it. I'd love to know a less lines of code way to do this.

    0 讨论(0)
  • 2020-12-10 09:46

    Instead of doing the following codes below:

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

    Do this:

    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 of the cell formatting, browse here on Antonio Bello's blog, it's where I got the idea. ^_^ I also asked here on SO the same question two days ago, and got the same answers like you, and I know that it's not what you want to do too. Hope it helps you.

    0 讨论(0)
  • 2020-12-10 09:46

    Your design is so strange. I have another approach is to override ToString() method of your classes (Service and City) like this:

    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 that works OK. Again, your design is a little strange ^_^

    0 讨论(0)
提交回复
热议问题