【发布时间】: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