繁体   English   中英

使用DataTemplate在WPF中通过LINQ to SQL进行双向绑定,以获取ListBox的ListItem的属性

[英]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 IDENTITYname 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上设置它会引发同样的问题,同时将其设置为OnInsertNever ,可以解决问题。

但是,在这两个值上设置它会使我的应用程序仅部分运行,数据会显示,但更改不会持久保存到数据库中。 (我在编辑应用程序上的数据后用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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM