【问题标题】:How to bind wpf ComboBox to Linq to SQL Foreign Key Property如何将 wpf ComboBox 绑定到 Linq to SQL 外键属性
【发布时间】:2010-01-16 03:56:06
【问题描述】:

我有一个 Linq to SQL EntitySet,两个表之间有一个外键关系。有问题的表是一个任务表(称为问题)和一个部门表。外键是部门名称(保证唯一)。我遇到了一个问题,如果加载了相应的数据,您将无法更改 Linq to 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;
    }
}

我必须对自己诚实,我在这里的工资等级已经超出了我的水平,但那是你学得最多的时候。..

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

感谢您的所有帮助

迈克

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

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

模型

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

视图模型

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

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

  • 一个包含一个实例的属性 视图模型类
  • 在构造函数中实例化视图模型并将数据上下文设置为视图模型的代码
  • 后面的其余代码是事件处理程序,最终将被命令替换

我多次阅读 Josh Smith 的优秀文章并探索了示例代码。我的大部分格式都基于此。 Chris(下)列出的线程有大量或新的材料供我探索,因此我将花一些时间深入研究并尝试确定如何最好地重构事物。这已经远远超出了一些 ComboBox 无法正常工作的范围,事实上,最初的部分问题是组合框被绑定到两个不同的数据上下文。在我拥有一个可管理的架构之前,我认为我在尝试修补问题时弊大于利。

我可能会在稍后回来为 Chris 打勾

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

【问题讨论】:

  • 好的,我完成了这项工作,但解决方案是如此可怕的黑客攻击,我感到畏缩。使用帖子末尾的事件,我向“UpdatingQuery”类添加了一个属性,然后在进行查询更改时将其设置为true。然后,我向 ChangeDepartment 添加了一个检查,以排除更新期间的更改。哎呀我真的需要找到正确的方法,我讨厌学习坏习惯!

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


【解决方案1】:

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

我建议您阅读Josh Smith's article on MVVM,它将让您深入了解 WPF 及其绑定功能。一旦您了解 WPF 的工作原理,在 WPF 中完成您想要做的事情就很容易了。

祝你好运!

【讨论】:

  • 如果我理解的话,我需要同时保留一个 IQueryable 来管理 Linq 和一个 ObservableCollection 来绑定到?每当对数据库进行更改时,它都会对 IQueryable 进行更改,然后用 IQueryable 的新副本覆盖 ObservableCollection?
  • yes ... 或者您可以将它进一步分开,并在 ObservableCollection 和 IQueryable 之间有一个层,这将是您在持久化之前收集工作单元的层。
  • 你能推荐一些关于这个的阅读吗?到目前为止,我的重构尝试导致了很多“已尝试附加或添加一个不是新的实体,可能是从另一个 DataContext 加载的......”异常我是否需要查询数据,设置用于绑定的 ObservableCollection 然后,如果进行了更改,则创建一个新的 DataContext,从中查询数据,然后将更改应用于该数据集并执行 SubmitChanges()?就目前而言,即使是对 db.GetChangeSet() 的调用也会引发异常(这对我来说似乎很奇怪,因为 GetChangeSet() 没有改变任何东西)
  • 只有在我丢弃并替换了我的 DataContext 之后才会出现错误。在那之前一切似乎都很好。
  • Josh Smith 的文章是我上面提到的必读文章,这里有一个关于 SO 的好问题,有大量的阅读材料链接。 stackoverflow.com/questions/1405739/… 我在 LINQ 方面的经验是有限的,但你真的不应该丢弃和替换整个数据上下文(至少如果我理解正确的话)。您需要将其视为(Data)Model-View-View Model,重要的是Data部分,View和ViewModel,不应该关心数据的CRUD操作是如何发生的(无论您使用,LINQ,nHibernate , ADO 等)。
猜你喜欢
  • 1970-01-01
  • 2016-09-25
  • 2011-09-07
  • 2014-12-08
  • 1970-01-01
  • 2011-04-17
  • 1970-01-01
  • 2015-03-14
  • 1970-01-01
相关资源
最近更新 更多