【问题标题】:LINQ many-to-many in WPF databinding pathWPF数据绑定路径中的LINQ多对多
【发布时间】:2011-02-04 21:53:47
【问题描述】:

在我的 c# WPF 应用程序中,我在运行时将列添加到 DataGrid,并通过 LINQ 从我的 SQL 数据库中填充。这工作正常,直到我尝试从我的多对多表中添加数据

这是我的数据库中 3 个相关表的简化版本:

documents: document_id, title
documents_keywords: document_id, keyword_id, value
keywords: keyword_id, name

我在 DataGrid 中想要的是 document.title 的一列,以及基于用户选择的 document.documents_keywords 中每条记录的一列。这是我的代码:

        DataGrid dataGrid = new DataGrid();
        dataGrid.Columns.Add(new DataGridTextColumn
        {
            Header = "Title",
            Binding = new Binding("title")
        });
        foreach (string keywordName in keywordsListBox.SelectedItems)
        {
            dataGrid.Columns.Add(new DataGridTextColumn
            {
                Header = keywordName,
                Binding = new Binding("documents_keywords.FirstOrDefault(kw => kw.keyword.name.Equals(\""+keywordName+"\")).value")
            });
        }

        dataGrid.ItemsSource = from d in db.documents select d;

我得到了关键字标题,但单元格都是空白的。绑定在 FirstOrDefault 失败:

System.Windows.Data Error: 40 : BindingExpression path error: 'FirstOrDefault(d_k => d_k.keyword.name.Equals("Order#"))' property not found on 'object' ''EntityCollection`1' (HashCode=7935090)'. BindingExpression:Path=documents_keywords.FirstOrDefault(d_k => d_k.keyword.name.Equals("Order#")).value; DataItem='document' (HashCode=5781744); target element is 'TextBlock' (Name=''); target property is 'Text' (type 'String')

实现此目的的最佳方法是什么?请原谅我,因为这是我第一次接触 WPF 和 LINQ。

【问题讨论】:

    标签: c# wpf linq data-binding


    【解决方案1】:

    我尝试重写您的代码,但这不是一件容易的事,我不确定它是否有效。 我已将每列的绑定设置为数组Keywords["+i+"]" 而不是documents_keywords.FirstOrDefault( 的顺序索引,并更改了ItemSource 的结构。

    我没有机会亲自检查此代码,所以如果您有任何问题,请在评论部分写出来。

        DataGrid dataGrid = new DataGrid();
        dataGrid.Columns.Add(new DataGridTextColumn
        {
            Header = "Title",
            Binding = new Binding("title")
        });
        //all possible keywords
        var items = db.keywords.Select(k => new {Id = k.keyword_id, Name = k.name}).ToArray();
        //selected keywords ordered by id
        var selected = (from item in items
                       where keywordsListBox.SelectedItems.Contains(item.Name)
                       orderby item.Id
                       select item)
                       .ToArray();
        //create columns and bind them
        for(int i = 0; i < selected.Length; i++)
        {
            dataGrid.Columns.Add(new DataGridTextColumn
            {
                Header = selected[i].Name,
                Binding = new Binding("Keywords["+i+"]")
            });
        }
    
        var documents = (from d in db.documents
                         select new{ 
                            d.title, 
                            //All related keywords
                            Keywords = d.documents_keywords.Select(dk => 
                                           new { Id = dk.keywoard_id, Value = dk.value})
                                          .ToList()}) 
                        .AsEnumerable()
                        .Select(doc => new {
                            title = doc.title,
                            //Only selected keywords with default null values
                            Keywords = (from si in selected
                                       join k in doc.Keywords on si.Id equals k.Id into j
                                       from ji in j.DefaultIfEmpty(new { Id = si.Id, Value = null})
                                       orderby ji.Id
                                       select ji.Value)
                                       .ToArray()
                            });
       dataGrid.ItemsSource = documents.ToList();
    

    【讨论】:

    • 抱歉,回复晚了 - 这个项目在优先级列表中很远,我刚刚回到它。您的解决方案在最后一行出现错误,但考虑到复杂性,我想我会尝试不同的方法。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-09-27
    • 2019-11-14
    • 1970-01-01
    • 2014-10-15
    • 2013-03-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多