[英]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.