2013-06-01 51 views
1

我有一个DataGridView和我想要显示的对象列表。绑定对象DataGridView C#

的对象是这些:

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 
} 

在我的形式我绑定的旅游对象这样的名单:

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

,我得到如下:

enter image description here

我想获得服务的名称,来源城市和命运C而不是。

在此先感谢。

回答

2
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; 

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

感谢您的回答。我如何更改标题文本? – ehh

+0

@ehh你指的是DataGrid的头?如果是,您可以在datagridview的属性中更改它。 –

+0

是的,谢谢。我想知道它是否可以作为匿名方法的一部分来完成。 Servicename没有“服务名称”(或不同的语法) – ehh

0

你的设计是如此的陌生。我有另一种方法是重写这样你的类(服务和城)ToString()方法:

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; 
    } 
} 

这工程确定。同样,你的设计是有点奇怪^ _^

2

而不是做下面的下面的代码:

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

这样做:

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

然后,手动添加列:

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); 

然后,添加一个单元格格式事件处理程序的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; 
} 

对于单元格格式的一个完整的指南,浏览here安东尼奥·贝洛的博客,它是在那里我得到了主意。^_^ 我也在这里问过两天前的同一个问题,并得到了和你一样的答案,而且我知道这不是你想要做的。希望它可以帮助你。

0

CellFormatting和BindProperty方法中的所有代码似乎过多。我的意思是,有些事情基本上是这样做的,但我认为它已经完成了。我在要绑定到网格行的对象中实现INotifyPropertyChanged,并将这些对象放入BindingList中。 BindingList直接用作网格的数据源。

这种方法意味着在映射到网格行的基本实体类中输入更多的内容,但我认为它可以在其他地方节省更多。要在类执行INotifyPropertyChanged:

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)); 
      } 
     } 
    } 

然后把一列在网格,并给它的“选定”一个DataPropertyName以匹配应该出现在该列在实体属性的名称。很明显,将所需的任何属性添加到网格中,以匹配实体的属性。关键是要确保通过对PropertyChanged的调用来实现属性设置器。

这可以让你的双向电网和你的对象的列表之间的结合。

我个人的看法:即使这是太多的代码。我发现自己经常写这类东西,做明显的:通过名称取一个属性,它映射到别的东西,知道的名称(如本例中的网格列)。这超出了我的理解,为什么这些东西不会自动挂钩。列表和网格应该有足够的意义来自己来确定这个基本安排。零行代码。好的,一行代码。 Grid.Datasource =列表。所以这就是我的做法。我很想知道更少的代码方式来做到这一点。