You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在TabControl的DataGrid中显示EF Core外键关联数据?

问题描述

使用Entity Framework Core + 数据库脚手架生成的实体,需要通过ID显示关联数据表的配料信息。简化后的Recipe实体类如下:

public partial class Recipe
{
    public Recipe()
    {
        InterchangeabilityIngredients = new HashSet<InterchangeabilityIngredients>();
    }

    public int Id { get; set; }
    public int IdBrand { get; set; }
    public int IdIngredient { get; set; }
    public double MassPart { get; set; }
    public double PercentWeight { get; set; }

    public virtual RubberBrand IdBrandNavigation { get; set; }
    public virtual Ingredient IdIngredientNavigation { get; set; }
    public virtual ICollection<InterchangeabilityIngredients> InterchangeabilityIngredients { get; set; }
}

设置DataGrid的ItemsSource代码:

IngredientsBrandGrid.ItemsSource = db.Recipe.AsQueryable().Where(x => x.IdBrand == currentbrid).ToList();

DataGrid的XAML结构:

<DataGrid x:Name="IngredientsBrandGrid" SelectionMode="Single" IsReadOnly="True" HorizontalAlignment="Left" Margin="0,0,0,60" AutoGenerateColumns="False">
    <DataGrid.Columns>
        <DataGridTextColumn Header="NameIngredient" Binding="{Binding IdIngredientNavigation.NameIngredient}" Width="200">
            <DataGridTextColumn.ElementStyle>
                <Style>
                    <Setter Property="TextBlock.TextWrapping" Value="Wrap" />
                </Style>
            </DataGridTextColumn.ElementStyle>
        </DataGridTextColumn>
        <DataGridTextColumn Header="MassPart" Binding="{Binding MassPart}"/>
        <DataGridTextColumn Header="PercentWeight" Binding="{Binding PercentWeight}"/>
    </DataGrid.Columns>
</DataGrid>

问题:NameIngredient列显示为空,尝试添加Include关联实体后仍无效:

IngredientsBrandGrid.ItemsSource = db.Recipe.Include(x=>x.IdIngredientNavigation).AsQueryable().Where(x => x.IdBrand == currentbrid).ToList();

注意:该DataGrid位于TabControl中,直接放在窗口中的DataGrid能正常显示数据。

解决方案

1. 延迟绑定数据到Tab激活时

TabControl默认延迟加载未激活Tab的内容,可能导致绑定时机过早,关联属性未完成初始化。监听TabControl的SelectionChanged事件,在目标Tab选中时重新加载数据:

private void TabControl_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    var tabControl = sender as TabControl;
    if (tabControl?.SelectedItem is TabItem targetTab && targetTab.Name == "目标Tab的名称")
    {
        IngredientsBrandGrid.ItemsSource = db.Recipe
            .Include(x => x.IdIngredientNavigation)
            .Where(x => x.IdBrand == currentbrid)
            .ToList();
    }
}

2. 验证EF Core的关联配置

检查DbContext中的Fluent API配置,确认Recipe与Ingredient的外键关联正确:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Recipe>(entity =>
    {
        entity.HasOne(d => d.IdIngredientNavigation)
            .WithMany(p => p.Recipes) // 对应Ingredient中的Recipe集合属性,无集合则用.WithOne()
            .HasForeignKey(d => d.IdIngredient)
            .OnDelete(DeleteBehavior.ClientSetNull);
    });
}

3. 调试确认关联实体加载状态

在数据绑定前添加调试断点,检查查询返回的Recipe对象中IdIngredientNavigation是否为null:

var recipes = db.Recipe
    .Include(x => x.IdIngredientNavigation)
    .Where(x => x.IdBrand == currentbrid)
    .ToList();
// 调试查看recipes中每个对象的IdIngredientNavigation是否有值
IngredientsBrandGrid.ItemsSource = recipes;

若为null,需检查数据库中IdIngredient对应的Ingredient记录是否存在,或外键配置是否错误。

4. 调整Include调用顺序

确保Include在Where之前调用(EF Core会自动优化,但规范写法可避免潜在问题):

IngredientsBrandGrid.ItemsSource = db.Recipe
    .Include(x => x.IdIngredientNavigation)
    .Where(x => x.IdBrand == currentbrid)
    .ToList();

5. 临时启用延迟加载排查

启用EF Core延迟加载,确认是否为加载问题(不建议长期使用,易引发N+1查询):
在DbContext构造函数中添加:

public YourDbContext(DbContextOptions<YourDbContext> options) : base(options)
{
    ChangeTracker.LazyLoadingEnabled = true;
}

实体中IdIngredientNavigation已为virtual属性,满足延迟加载条件。若启用后能显示,说明之前的Include未生效,需排查查询逻辑。

内容的提问来源于stack exchange,提问作者Miriskava

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 16:15:19