[英]Two way binding in WPF trough LINQ to SQL for the property of a ListItem of a ListBox using a DataTemplate
我是C#和WPF的新手。 尽管我阅读了大量的文档,教程和以前的问题,但我似乎无法找到我的场景。
我在C#中有一个WPF应用程序,其中包含一个包含ListBox的Window。 ListBox定义了一个DataTemplate,用于为每个ListItem显示带有TextBox的项目。
我在同一台机器上有一个Microsoft SQL Express服务器,它包含一个名为Test
的数据库,其中包含一个名为Client
的视图,它公开了另一个表的列id INT PRIMARY KEY IDENTITY
和name VARCHAR(50) NOT NULL
,以及一个名为Client_update(@id, @name)
的存储过程Client_update(@id, @name)
id
,@ name
Client_update(@id, @name)
通过同一个表上的简单UPDATE语句设置id
为@id
的客户端的name
列。
我想要实现的是在窗口加载时填充ListBox,并通过将焦点切换到另一个组件来对数据(包含在文本框中)的更改持久保存到数据库(通过存储过程)的GUI。
我使用Visual Studio向项目中添加了一个新的LINQ to SQL Classes元素,从而创建了一个名为DataClassesDataContext
的DataContext类。 我使用Visual Studio中的OR Designer将视图映射到Class Client
,将存储过程映射到Client_update(id, name)
。 然后我设置(再次使用OR Designer的GUI)表Client
的主键为id
,其默认编辑方法为Client_update(id, name)
(负责匹配存储过程和方法的参数)。
我的XAML代码(文件MainWindow.xaml.cs
)是:
<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>
我已将TextBox Text属性设置为绑定到要在运行时在稍后显示的代码隐藏中设置的源的name
属性,在TwoWay模式下。 TextBox上的数据更新的默认触发器应该是OnLostFocus,所以我没有指定它。
我的代码隐藏(文件MainWindow.cs
)是:
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;
}
}
}
首先,应用程序将无法运行。 System.Data.Linq.dll
中类型System.InvalidOperationException
的未处理异常,其中包含“成员'id'的错误AutoSync规范”。 被扔了。
在线搜索我发现,默认情况下,OR Designer会将AutoSync规范设置为主键列上的Always
。 在OnUpdate
上设置它会引发同样的问题,同时将其设置为OnInsert
或Never
,可以解决问题。
但是,在这两个值上设置它会使我的应用程序仅部分运行,数据会显示,但更改不会持久保存到数据库中。 (我在编辑应用程序上的数据后用Microsoft SQL Management Studio手动检查)
什么是AutoSync参数以及为什么会引发异常? 这是在这种情况下定义双向绑定的正确方法,还是我完全走错了方向? 如果是这样,你能否给我任何提示,指出我正确的策略?
PS我很抱歉,如果代码没有正确突出显示,我已阅读并尝试使用语法来应用Prettify,但由于某种原因,XAML没有选项,甚至使用XML和C#(cs)作为语言标签不起作用,我不明白为什么。
编辑#1:突出显示正在工作,它只是未在预览中显示。
编辑#2:修正了一些拼写错误,视图的名称,存储过程和类是单一的。 (即Client
不是Clients
)
尝试将dataContext
定义为全局变量。 那么只要改变从对象dataContext
需要提交,调用dataContext.SubmitChanges();
。 应该按需要通过调用SubmitChanges()
方法同步到数据库(实时太昂贵):
DataClassesDataContext dataContext = new DataClassesDataContext();
......
private void ButtonSubmit_Click(object sender, RoutedEventArgs e)
{
dataContext.SubmitChanges();
}
更新:( 作为评论的respoind)
这是我所知道的使用LINQ to SQL持久更改数据库的方式。 DataContext
通过跟踪对从db检索的实体的更改来工作,当SubmitChanges
调用发送回db的所有更改时。
TwoWay
模式绑定不涉及application-to-db和db-to-application。 它是[绑定UI控件属性] -to- [绑定源],反之亦然。 当用户在TextBox中更改名称时,Client实体中的name属性将反映该更改,如果实体中的名称从代码更改,TextBox将显示更新的名称。 在这种情况下,这就是双向的意思。 但所有这些更改都在应用程序中,在调用SubmitChanges
之前不会提交给db。
我不完全了解AutoSync
属性,你可以参考这个SO答案 ,看看是否有助于你理解它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.