如何将Wpf ComboBox绑定到Linq到SQL外键属性

时间:2010-01-16 03:56:07

标签: c# wpf linq-to-sql xaml data-binding

我有一个Linq to SQL EntitySet,两个表之间有一个外键关系。有问题的表是一个任务表(称为问题)和一个部门表。外键是部门名称(保证唯一)。我遇到了一个问题,如果加载了相应的数据,就无法将Linq更改为SQL FK字段。

ViewModel(不是真正的MVVM,我在学习xaml,WPF和Linq-SQL时尝试练习这些概念)

public class StatusBoardViewModel : INotifyPropertyChanged
{
    OIConsoleDataContext db = new OIConsoleDataContext();

    private IQueryable<Issue> issues;
    public IQueryable<Issue> Issues
    {
        get { // Lazy load issues if they have not been instantiated yet
            if (issues == null) {
                QueryIssues();
            }
            return issues; 
        }
        set {
            if (issues != value) {
                issues = value;
                OnPropertyChanged("Issues");
            }
        }
    }

    private IQueryable<Department> departments;
    public IQueryable<Department> Departments
    {
        get {
            // Lazy load departments if they have not been instantiated yet
            if (departments == null) {
                QueryDepartments();
            }
            return departments;
        }
        set {
            if (departments != value) {
                departments = value;
                OnPropertyChanged("Departments");
            }
        }
    }

    private void QueryDepartments()
    {
        Departments = from d in db.Departments
                      orderby d.DeptName
                      select d;
    }

    public void QueryIssues()
    {
        Issues = from i in db.Issues
                 where i.IssIsOpen == true
                 orderby i.IssDueDate
                 select i;
         // ....
    }

    #region INotifyPropertyChanged Members
}

我的组合框:

<ComboBox x:Name="DeptComboBox" 
  ItemsSource="{Binding Departments}" 
  DisplayMemberPath="DeptName"
  SelectedValuePath="DeptName"
  SelectedValue="{Binding Path=Issues/IssDepartment, Mode=TwoWay}"
  Grid.Column="2" Grid.ColumnSpan="2" Grid.Row="3" Margin="6,7,115,5"
  IsSynchronizedWithCurrentItem="True" /> 

现在它显示组合框正常并将选择默认为正确的部门但是如果进行更改它会抛出异常'System.Data.Linq.ForeignKeyReferenceAlreadyHasValueException'

我尝试添加

   SelectionChanged="DeptComboBox_SelectionChanged" 

到组合框,然后使用以下代码删除部门引用,然后添加新的代码。它似乎工作正常,但我发现如果过滤器设置导致linq查询被更改,那么当Selection_Changed事件触发时,更改之前的当前项目会将其部门更改为新默认项目部门的值。我找不到一种方法来判断选择更改事件是来自用户而不是绑定属性来防止这种情况。除此之外,我对代码的使用感到不满意,因为它似乎应该是绑定或至少某种价值转换器。

// This was an attempt to work around that did not work
// The referneces are passed from the Window1 event handler
public void ChangeDepartment(Issue currentIssue, Department currentDept)
{
    if (currentIssue != null) {
        currentIssue.Department = null;
        currentIssue.Department = currentDept;
    }
}

我必须诚实地对待自己,我的薪水等级超过了我的薪水等级,但是当你学到最多的时候......

我应该如何处理?我已经阅读了十几篇关于这个问题的文章,发现它们是相互矛盾的,并且像泥浆一样清晰。

感谢您的所有帮助SO

麦克

更新的 我和下面的Chris Nicol进行了非常有用的讨论,如果我对事情有了更好的处理,他可能已经有了勾选标记。我认为我最大的问题是我必须同时学习SQL,Linq,WPF和数据库设计。我有关于所有主题的优秀书籍,但它们不包括互操作性。例如,C#2008中的Pro Linq很棒......除了它在WPF中没有谈论Linq,

我试图尽可能地做“MVVMish”,但是,在之前的一些错误的开始之后,我认为一次学习太多了。在实践中我认为我接近MVVM,除了没有命令,我在ViewModel类中从后面的代码中的事件处理程序执行方法。我假设这将使以后在命令结构中重构变得相当容易。我的应用程序结构如下:

模特

  • Linq to SQL dbml files
  • DataErrorInfo验证的部分类

ViewModel

  • DataContext
  • 任务,员工和部门的IQueryable集合
  • 添加/编辑窗口视图
  • 使用的选定任务属性
  • 要绑定到视图的某些属性,例如ShowDetailListItems(),它触发不同的列表框ItemTemplate,并且本身绑定到一个复选框。
  • 执行查询的方法
  • 打开窗口以添加或编辑任务以及从所述窗口返回时submitChanges()的方法。

视图绑定到viewmodel,后面的代码包含:

  • 包含实例的属性 viewmodel类
  • 用于在构造函数中实例化viewmodel并将datacontext设置为viewModel的代码
  • 后面的代码的其余部分是最终将被命令替换的事件处理程序

我多次阅读Josh Smiths的优秀文章并探索了示例代码。我的大部分格式都基于此。克里斯(下面)列出的主题有一些或者新的材料供我探索,所以我会花一些时间深入研究并尝试确定如何最好地重构事物。这远远超出了一些ComboBoxes无法正常工作,事实上,原始问题的一部分是组合框被绑定到两个不同的数据上下文。在我拥有一个可管理的架构之前,我认为我正在做更多的伤害,试图修补它。

我可能会稍后带回Chris的复选标记

Grrr:“已尝试附加或添加一个非新的实体,可能是从另一个DataContext加载的......”

1 个答案:

答案 0 :(得分:2)

我建议将您的数据访问层与ViewModel分开并使用可观察的集合。一旦你更好地利用MVVM,这种事情就不那么难了。

我建议您阅读Josh Smith's article on MVVM,它将为您提供对WPF及其绑定功能的深刻见解。一旦你理解了WPF的工作原理,完成你在WPF中尝试做的事情就很容易了。

祝你好运!