EF,WinForms:如何向DataGridView添加相关的导航属性?

时间:2014-04-26 19:52:45

标签: c# winforms entity-framework datagridview ado.net

我的数据库中有User和UserGroup表:

enter image description here

我按照本教程http://msdn.microsoft.com/en-us/data/jj682076.aspx

生成了EF模型(数据库优先)和DataSource for User

在我的表单上,我创建了BindingSource(bsUsers)并将DataGridView绑定到它,因此它显示了Ids和Usernames。

以下是我在表单启动时加载数据的方法:

_myDbContext = new MyDbContext();

_myDbContext.Users.Load();

bsUsers.DataSource = _myDbContext.Users.Local.ToBindingList();

但是现在我想在同一个DataGridView中显示GroupName。最好的方法是什么?

我尝试在UserGroup.GroupName列中指定DataPropertyName,但它不起作用,单元格仍为空。

到目前为止,我找到的唯一解决方案是创建一个新的未绑定列并手动填充:

foreach (var item in (IList<User>)bsUsers.DataSource) 
{
    dgw.Rows[i].Cells["GroupName"].Value = item.UserGroup.Name; 
}

但它看起来不是一个好方法。例如,在更改用户组后,我将需要再次更新它,或者在添加新记录时。

2 个答案:

答案 0 :(得分:5)

找到了更好的方法:http://www.developer-corner.com/blog/2007/07/19/datagridview-how-to-bind-nested-objects/(仅适用于只读,不适用于DataGridView中的编辑)

public static class BindingHelper
{
    // Recursive method that returns value of property (using Reflection)
    // Example: string groupName = GetPropertyValue(user, "UserGroup.GroupName");
    public static object GetPropertyValue(object property, string propertyName)
    {
        object retValue = "";

        if (propertyName.Contains("."))
        {
            string leftPropertyName = propertyName.Substring(0, propertyName.IndexOf("."));

            PropertyInfo propertyInfo = property.GetType().GetProperties().FirstOrDefault(p => p.Name == leftPropertyName);

            if (propertyInfo != null)
            {
                retValue = GetPropertyValue(
                    propertyInfo.GetValue(property, null),
                    propertyName.Substring(propertyName.IndexOf(".") + 1));
            }
        }
        else
        {
            Type propertyType = property.GetType();
            PropertyInfo propertyInfo = propertyType.GetProperty(propertyName);
            retValue = propertyInfo.GetValue(property, null);
        }

        return retValue;
    }
}

在列中,DataPropertyName设置为UserGroup.GroupName

enter image description here

CellFormatting事件中,我将所有列“绑定”的所有列称为嵌套属性(.中有DataPropertyName)以显示其值:

private void dgwUsers_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
    var dgw = (DataGridView) sender;
    DataGridViewColumn column = dgw.Columns[e.ColumnIndex];
    DataGridViewRow row = dgw.Rows[e.RowIndex];

    if (column.DataPropertyName.Contains("."))
    {
        e.Value = BindingHelper.GetPropertyValue(row.DataBoundItem, column.DataPropertyName);
    }
}

此外,我将ComboBox绑定到相同的BindingSource,允许更改当前所选用户的组。要更新相应DataGridView单元格中的值,我在ComboBox的SelectedIndexChanged事件中执行此操作:

private void cbbUserGroup_SelectedIndexChanged(object sender, EventArgs e)
{
    Validate();
    dgwUsers.UpdateCellValue(dgwUsers.Columns["GroupName"].Index, dgwUsers.CurrentRow.Index);
}

答案 1 :(得分:0)

您可以简单地覆盖模型中的ToString()。即使我强烈建议使用ViewModel。

public class UserGroup{

public int Id { get; set; }
public string GroupName { get; set; }

public override string ToString() {

    return GroupName;
}