【问题标题】:WPF DataGrid Parent Child DataWPF DataGrid 父子数据
【发布时间】:2011-03-22 14:38:53
【问题描述】:

我是 WPF/C#/NET 的新手,但我一直在通过编写一些小练习来学习。

无论如何,我被困住了。我在这里和谷歌上搜索过,但找不到答案,或者更正确的是找不到我能理解的答案。

我的问题是......使用实体框架我有两个表。一份用于员工详细信息,一份用于公司详细信息。员工为 0 或 1 家公司工作。

我想通过 WPF/XAML 定义一个数据网格来导​​航员工。但在每个员工行中,我想显示他们工作的公司名称(如果有关系)或在没有相关公司记录的情况下显示“失业”。

我没有提供表格的详细信息,因为这真的无关紧要 - 问题是在单个数据网格中显示来自父/子关系的连接信息。

我不知道解决这类问题的最佳方法是什么,我假设是 WPF/DataGrid,所以我非常感谢有关如何去做、绑定(假设 WPF)甚至是示例的帮助WPF/XAML

提前致谢。

【问题讨论】:

    标签: c# wpf entity-framework datagrid parent-child


    【解决方案1】:

    有很多方法可以实现这一点 - 您可以尝试的一种方法是创建一个封装您想要显示的数据的视图模型 - 例如

    public class EmployeeViewModel
    {
        private readonly Employee _employee;
    
        public EmployeeViewModel(Employee employee)
        {
            _employee = employee;
        }
    
        public string Name { get { return _employee.Name; } }
        public string CompanyName { get { return _employee.Company == null ? "Unemployed" : _employee.Company.CompanyName; } }
    }
    

    然后,给定IEnumerable<Employee>,您可以将员工数据投影到此视图模型中,并将其设置为 DataGrid 的 ItemsSource - 例如

    IEnumerable<Employee> employees = GetEmployeesFromDatabase();    
    DataGrid1.ItemsSource = employees.Select(x => new EmployeeViewModel(x));
    

    您通常会在此处通过 xaml 绑定设置 ItemsSource,而不是直接在代码中设置,但这将涉及使用父 ViewModel 设置为 View 的 DataContext,我试图让事情变得简单。

    使用 DataGrid 完成此操作的另一种方法是放弃使用视图模型,直接绑定到 IEnumerable&lt;Employee&gt; 集合并显式设置列绑定 - 例如

    <DataGrid ItemsSource="{Binding Employees}" AutoGenerateColumns="False">
        <DataGrid.Columns>
            <DataGridTextColumn Header="Employee Name" Binding="{Binding Name}" />
            <DataGridTextColumn Header="Company Name" Binding="{Binding Company.Name}" />
        </DataGrid.Columns>
    </DataGrid>
    

    请注意,在第二个示例中,您不会在没有员工关联公司的公司名称列中看到“失业”。

    编辑:为了阐明关于从绑定到视图的“主”视图模型上的属性设置网格项目源的要点,您可以创建一个表示整个当前视图的 ViewModel 类。例如

    public class MainViewModel
    {
        private readonly IEnumerable<Employee> _employees;
    
        public MainViewModel(IEnumerable<Employee> employees)
        {
            _employees = employees;
        }
    
        public IEnumerable<Employee> Employees
        {
            get { return _employees; }
        }
    }
    

    您可以将其设置为 Window / UserControl 的 DataContext。

    例如在简单的情况下,您可以在 Window 的构造函数中执行此操作(尽管对于 WPF 应用程序而言,对数据库的调用实际上应该是异步的)。

     public MainWindow()
     {
         InitializeComponent();
         DataContext = new MainViewModel(GetAllEmployees());
     }
    

    然后你可以像这样在你的 Grid 上设置绑定:

    <DataGrid ItemsSource="{Binding Employees}" ...
    

    然后,主窗口的数据上下文将用于其中包含的所有子控件,除非您在子控件上显式设置 DataContext。当您拥有具有许多属性和命令的更复杂的 ViewModel 时,这种技术会变得很有用。如果您有兴趣了解更多信息,您应该查看 MVVM 模式以及 Prism / Caliburn 框架中的一个或两个。

    【讨论】:

    • 谢谢史蒂夫。几个问题。在我的代码中,我没有像您的示例那样设置网格的 ItemsSource。我只是有 ItemsSource="{Binding}" 然后我在 Window_Loaded 事件上将 grids.DataContext 设置为我的 ObjectSet。现在,当我尝试您的第二个示例 Company.Name 时,公司名称不会显示任何内容。如果我只有公司,那么我将获得正确公司记录的行 ID。同样在我的设计师 Company.Name 中, .Name 位是红色而不是蓝色。我做错了什么?
    • 嗨,克里斯,设置网格的 DataContext 后,您的 ItemsSource="{Binding}" 与将整个视图绑定到具有Employees属性的更高级别的视图模型相同的结果,所以那里没有问题。 {Binding Company.Name} 假定您的公司对象上有一个名为 Name 的属性 - 如果不是这种情况,您需要将 Company.Name 替换为 Company.CompanyName 或 Company 对象上所需的任何属性。
    • Steve,Company 表确实有一列 Name。公司实体具有名称属性。但我唯一绑定的是员工的集合。我想我在这里错过了一个基本步骤......
    • 您应该能够以这种方式绑定员工集合。我假设员工类有一个名为 Company 的属性?如果是这样,则 {Binding Company.Name} 属性路径语法将导航到每行的 Employee 的 Company 属性,然后获取 Company 的 Name 属性。查看是否有任何绑定错误的一个好方法是在调试模式下运行并查看 Visual Studio 中的输出窗口(调试 -> 窗口 -> 输出) - 任何绑定错误通常都会出现在那里。
    • 还有一件事,如果您使用的是旧版本的实体框架(V4.0 之前的任何版本),那么 Company 属性默认不会延迟加载 - 您可能需要使用“包含”语句在您的 EF 查询中。这通常是避免 Select n+1 问题的好主意。
    猜你喜欢
    • 2012-04-04
    • 1970-01-01
    • 2013-11-06
    • 2010-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多