2010-01-16 93 views
1

我有一个Linq到SQL EntitySet与两个表之间的外键关系。有问题的表是一个任务表(称为问题)和一个部门表。外键是部门名称(保证唯一)。我遇到了一个问题,即如果加载相应的数据,则无法将Linq更改为SQL FK字段。如何绑定wpf组合框到Linq到SQL外键属性

视图模型(事实并非如此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; 
    } 
} 

我必须对自己诚实,我在过我的工资级别在这里,但是当你学到的最诶这是..

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

感谢您的帮助,所以

迈克

我曾与下面克里斯·尼科尔一个非常有益的讨论,他很可能已经有对勾,如果我有东西更好地处理更新。我认为我最大的问题是我必须一次性学习SQL,Linq,WPF和数据库设计。我拥有关于所有主题的优秀书籍,但不包括互操作。例如,C#2008中的Pro Linq非常棒......除了它根本没有谈论WPF中的Linq,

我试图尽可能地将事情做成“MVVMish”,但是之前几次错误的启动之后,我决定一次学习太多东西了。在实践中,我认为我接近MVVM,除了没有命令,我在ViewModel类中从后台代码中的事件处理程序中执行方法。我认为这会使得稍后在指挥结构中进行重构变得相当容易。我的应用程序的结构如下:

示范

  • 的LINQ to SQL的dbml文件
  • 为DataErrorInfo验证部分类

视图模型

  • DataCon文本
  • 对于由添加/编辑窗口视图中使用
  • 一些性质的视图绑定到诸如ShowDetailListItems(任务,公司雇员和部门
  • 选定的任务属性IQueryable的集合)触发不同的列表框ItemTemplate并且本身绑定到一个复选框。
  • 执行查询的方法
  • 打开窗口以添加或编辑任务并在从所述窗口返回时提交更改()的方法。

绑定到视图模型和后面的代码包含:

  • 持有的 视图模型类
  • 代码实例来实例化的构造器的视图模型的属性和将数据上下文设置为viewModel
  • 其余的代码是最终将被命令替换的事件处理程序

我已阅读Josh Smiths优秀文章多次,并探讨了示例代码。我的大部分格式都基于此。 Chris(Below)列出的主题有很多或新的材料供我探索,因此我将花一些时间深入探讨并试图确定如何最好地重构事情。这已经远远超出了一些ComboBoxes无法工作的地步,事实上,原始问题的一部分是组合框被绑定到两个不同的数据上下文。直到我有一个可管理的体系结构,我认为我正在做更多的伤害,试图修补东西。

我可能会回来后与克里斯

勾选

哎呀:“尝试已经取得了附加或添加,是不是新的,可能已经从另一个DataContext的加载实体...”

+0

好的,我做了这项工作,但解决方案是这样一个令人恐惧的黑客我畏缩。从我的帖子末尾使用事件,我添加了一个属性到类'更新查询',然后将其设置为true,同时使查询更改。然后,我向ChangeDepartment添加了一个检查以排除更新期间的更改。 OUCH我真的需要找到正确的方式,我讨厌学习坏习惯! – 2010-01-16 07:46:22

回答

2

我会建议分隔您的数据访问层从您的ViewModel和使用可观察的集合。一旦你更好地利用MVVM,这种事情并不难。

我建议您阅读Josh Smith's article on MVVM,它会让你对WPF及其绑定功能有很好的了解。一旦你理解了它的工作方式,完成你在WPF中所要做的事情是很容易的。

祝你好运!

+0

如果我的理解,那么我将需要保持一个IQueryable 管理Linq和一个ObservableCollection 绑定?任何时候对数据库进行更改时,都会对IQueryable进行更改,然后使用IQueryable的新副本覆盖ObservableCollection? – 2010-01-17 17:53:42

+0

是的......或者你可以将它分离得更远,并且在ObservableCollection和IQueryable之间有一层,它将成为你的图层,用于在持续之前收集工作单元。 – 2010-01-18 15:26:22

+0

你能提出一些关于这方面的阅读吗?到目前为止,我对重构的尝试导致了很多“试图附加或添加一个不是新的实体,可能是从另一个DataContext加载的......”例外 我是否需要查询数据,设置ObservableCollection进行绑定,如果进行了更改,则创建一个新的DataContext,从中查询数据,然后将更改应用到该数据集并执行SubmitChanges()?现在,即使调用db.GetChangeSet()也会抛出异常(这对我来说似乎很奇怪,因为GetChangeSet()不会改变任何东西) – 2010-01-20 18:25:35