在WPF数据绑定路径中LINQ多对多

时间:2011-02-04 21:53:47

标签: c# wpf linq data-binding

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

这是我的db:

的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。

1 个答案:

答案 0 :(得分:0)

我试图重写你的代码,但这不是一件容易的事,我不确定它是否有效。 我已将每列的绑定设置为数组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();