C# WPF中使用DataTemplate通过LINQ到SQL对ListBox的ListItem属性进行双向绑定
我对C#和WPF还很陌生。尽管我已经阅读了大量的文档、教程和以前的问题,但我似乎找不到我的场景 我所拥有的 我有一个C#格式的WPF应用程序,其中一个窗口包含一个列表框。 ListBox定义一个DataTemplate来显示其项,每个ListItem都有一个文本框 我在同一台计算机上有一个Microsoft SQL Express server,其中包含一个名为C# WPF中使用DataTemplate通过LINQ到SQL对ListBox的ListItem属性进行双向绑定,c#,wpf,linq,binding,listbox,C#,Wpf,Linq,Binding,Listbox,我对C#和WPF还很陌生。尽管我已经阅读了大量的文档、教程和以前的问题,但我似乎找不到我的场景 我所拥有的 我有一个C#格式的WPF应用程序,其中一个窗口包含一个列表框。 ListBox定义一个DataTemplate来显示其项,每个ListItem都有一个文本框 我在同一台计算机上有一个Microsoft SQL Express server,其中包含一个名为Test的数据库,该数据库的视图名为Client,该视图公开另一个表的id INT主键标识列和name VARCHAR(50)NOT N
Test
的数据库,该数据库的视图名为Client
,该视图公开另一个表的id INT主键标识列和name VARCHAR(50)NOT NULL
,以及一个名为Client\u update(@id,@name)的存储过程
通过同一表上的简单UPDATE语句设置其id
为@id
的客户机的名称
列
我正在努力实现的目标
我试图实现的是在窗口加载时填充ListBox,并通过将焦点切换到GUI的另一个组件,将对数据(包含在文本框中)的更改持久化到数据库(通过存储过程)
我所做的
我使用Visual Studio在我的项目中添加了一个新的LINQ to SQL Classes元素,从而创建了一个名为DataClassesDataContext
的DataContext类。
我使用了Visual Studio中的O-R设计器将视图映射到类客户机
,并将存储过程映射到方法客户机更新(id,name)
。然后我(再次使用O-R设计器的GUI)将表Client
的主键设置为id
,其默认编辑方法设置为Client\u update(id,name)
(注意匹配存储过程和方法参数)
我的XAML代码(文件MainWindow.XAML.cs
)是:
我所得到的
首先,应用程序不会运行。
抛出System.Data.Linq.dll
中类型为System.InvalidOperationException
的未处理异常,其中包含消息“成员'id'的自动同步规范不正确”
在线搜索我发现,默认情况下,O-R设计器会在主键列上将自动同步规范设置为始终
。将其设置为OnUpdate
会引发相同的问题,而将其设置为OnInsert
或Never
则会解决此问题
但是,将其设置为这两个值只允许我的应用程序部分运行,数据将显示,但更改不会持久化到数据库中。(在编辑应用程序上的数据后,我与Microsoft SQL Management Studio进行了手动检查)
我的问题是什么
AutoSync参数是什么?为什么它会引发异常?
在这种情况下,这是定义双向绑定的正确方法,还是我完全走错了方向?如果是这样的话,你能给我一些提示,告诉我正确的策略吗
p.S.如果代码没有正确突出显示,我很抱歉,我已经阅读并尝试使用语法来应用美观的东西,但是出于某种原因,XAML没有选项,而且甚至使用XML和C#(cs)作为语言标记也不起作用,我不知道为什么
编辑#1:高亮显示正在工作,只是没有显示在预览中
EDIT#2:修复了一些打字错误,视图名称、存储过程和类都是单壳的。(即Client
而不是Clients
)尝试将dataContext
定义为全局变量。然后,每当需要提交来自dataContext
的对象更改时,调用dataContext.SubmitChanges()代码>。通过调用SubmitChanges()
方法(成本太高,无法实时),应按需同步到数据库:
更新:(回复评论)
这就是我所知道的使用LINQtoSQL将更改持久化到数据库的方法DataContext
在SubmitChanges
调用发送回db的所有更改时,通过跟踪从db检索到的实体的更改来工作
TwoWay
模式绑定不指应用程序到数据库,也不指数据库到应用程序。它是[binding UI control property]-[binding source],反之亦然。当用户更改TextBox中的名称时,客户端实体中的name属性将反映该更改,并且如果实体中的名称从代码更改,TextBox将显示更新的名称。这就是双向在这种情况下的含义。但所有这些更改都在应用程序中,在调用SubmitChanges
get之前不会提交给db
我不完全了解AutoSync
属性,您可以参考,看看这是否有助于您理解它。@Blam您是说我不应该使用DataClassesDataContext类吗?数据上下文类不是LINQ到SQL交互的主要组件吗?另外,你说“你可以尝试一个类和一个属性并在集合中的db中更新”是什么意思?你能说得更具体一点吗?我不确定你是否能用DataContext做到这一点?如果使用属性创建自定义类,则可以在集合中执行更新。关于绑定到类的外观。谢谢您的回答,har07。你的解决方案似乎奏效了。虽然在我看来,这是一种粗略的解决方法,因为它试图更新整个数据上下文(可能包括一组比列表框的唯一来源大得多的信息),但这是正确的方法吗?然而,我可能弄错了:你会推荐它吗/你会在你的应用程序中使用它吗?我将尝试分析利弊。这似乎是这类事情的标准过程,如MSDN页面的“实现保存功能”部分所述:我认为只要将绑定声明为双向绑定,更改就会自动持久化,但显然这样做了
<Window x:Class="Test.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Loaded="Window_Loaded">
<ListBox x:Name="myListBox">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBox Text="{Binding Path=name Mode=TwoWay}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Window>
namespace Test
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
//Initialize the data context
DataClassesDataContext dataContext = new DataClassesDataContext();
//Define the query to retrieve the list of clients from the SQL Server
IEnumerable<Client> clients = from c in dataContext.Client
select c;
/* Set the item source to be the result of the query defined earlier
* (This also gets the query executed)
*/
myListBox.ItemsSource = clients;
}
}
}
DataClassesDataContext dataContext = new DataClassesDataContext();
......
private void ButtonSubmit_Click(object sender, RoutedEventArgs e)
{
dataContext.SubmitChanges();
}