直接用程式碼更改Datagridview某儲存格的資料,游標列竟沒存進去

danny
請教各位

我在 Datagridview1 的 姓名 欄位,直接修改時,存檔離開後,再進來看,有存進去

但是我如果是直接下指令:
Datagridview1.CurrentRow.Cells("姓名").Value = "test"
SqlDataAdapter1.Update(DataTable1)
Close()

明明有存檔了,再進來看,卻沒有存進去 (若有先跳到別列時,則會存進去)

是還需要下什麼指令才會更新嗎 ?

環境: Win7 , Visual Studio 2017 , SQL Server2012Express
o小高o
update好像要先設定updatecommand?

SqlDataAdapter 建構函式 (String, SqlConnection)


https://docs.microsoft.com/zh-tw/dotnet/api/system.data.sqlclient.sqldataadapter.-ctor?view=netframework-4.8#System_Data_SqlClient_SqlDataAdapter__ctor_System_Data_SqlClient_SqlCommand_

https://melomelo1988.pixnet.net/blog/post/167644203
danny
謝謝 o小高o

1.有設 UpdateCommand , 直接在 Datagridview1 上修改內容,是正常的

2.只有下指令(如下)時,才沒有存進去-----------問題
Datagridview1.CurrentRow.Cells("姓名").Value = "test"
SqlDataAdapter1.Update(DataTable1)
o小高o
那我覺得是不是CurrentRow數值一開始不對 >>因為 若有先跳到別列時,則會存進去
你可以試試看在這加上
MessageBox.Show(DataGridView1.CurrentRow.Index);
在這前面
Datagridview1.CurrentRow.Cells("姓名").Value = "test"
SqlDataAdapter1.Update(DataTable1)

所以沒改到正確的位置?
如果是這樣的話就變成你要改的時候先指定
DataGridView1.CurrentCell = DataGridView1.Rows[A].Cells[B];
再Datagridview1.CurrentRow.Cells("姓名").Value = "test";
應該就可以解掉
o小高o
PS: MessageBox.Show(DataGridView1.CurrentRow.Index.ToString());
抱歉應該要加.ToString() index應該是int 要轉string才能show
danny
謝謝 o小高o

應該不是 CurrentRow 的問題

我的測試如下:
1.滑鼠先點到DataGridView的第2列 , 按 更改姓名 按鈕, 輸入:test1 確定 , DataGridView上有看到姓名已更改了 , 按 關閉 按鈕 , 再進來,還是舊的姓名 ...........更改失敗,沒存檔
2.滑鼠先點到DataGridView的第2列 , 按 更改姓名 按鈕, 輸入:test2 確定 , DataGridView上有看到姓名已更改了 , 滑鼠再點到DataGridView的下一列 , 按 關閉 按鈕 , 再進來,有存檔成功
3.滑鼠先點到DataGridView的第2列的 姓名 儲存格,直接輸入:test3 , 按 關閉 按鈕 , 再進來,有存檔成功

程式碼如下:
Imports System.Data.SqlClient

Public Class member
    Dim xcon As New SqlConnection(sy_shop_constr)
    Dim da As SqlDataAdapter = New SqlDataAdapter
    Dim ds As New DataSet
    Dim dt As DataTable

    Private Sub member_Load(sender As Object, e As EventArgs) Handles Me.Load
        da_setting()
        Dbinit()
    End Sub

    Sub Dbinit()
        da.SelectCommand = New SqlCommand("Select * From member", xcon)
        da.Fill(ds, "member")

        DataGridView1.AutoGenerateColumns = False
        dt = ds.Tables("member")
        DataGridView1.DataSource = dt

        Dim xi As Integer = -1

        ' 顯示一個欄位
        xi = xi + 1
        DataGridView1.Columns.Add("代號", "代號")
        DataGridView1.Columns(xi).DataPropertyName = "no"
        DataGridView1.Columns(xi).Width = 65
        DataGridView1.Columns(xi).Frozen = True         '凍結欄位

        ' 顯示一個欄位
        xi = xi + 1
        DataGridView1.Columns.Add("姓名", "姓名")
        DataGridView1.Columns(xi).DataPropertyName = "name"
        DataGridView1.Columns(xi).Width = 80
    End Sub

    Sub da_setting()
        da.UpdateCommand = New SqlCommand("Update member SET [no] = @no, name = @name WHERE uno = @uno", xcon)
        With da.UpdateCommand
            .Parameters.Add("@no", SqlDbType.NVarChar, 10, "no")
            .Parameters.Add("@name", SqlDbType.NVarChar, 10, "name")
            .Parameters.Add("@uno", SqlDbType.Int, 0, "uno")
        End With
    End Sub

    Private Sub DataGridView1_RowValidated(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.RowValidated
        da.Update(dt)   '存檔
    End Sub

    '更改姓名
    Private Sub testButton_Click(sender As Object, e As EventArgs) Handles testButton.Click
        Dim xname As String = InputBox("請輸入姓名", "更改姓名")

        DataGridView1.CurrentRow.Cells("姓名").Value = xname
        da.Update(dt)   '存檔
    End Sub

    '關閉
    Private Sub CloseButton_Click(sender As Object, e As EventArgs) Handles CloseButton.Click
        Close()
    End Sub
End Class

P陳
存檔前要執行 datagridview1.EndEdit 的動作,
否則還存在 datagridview 中,
EndEdit 後才會回寫到 DataSource
danny
謝謝

存檔前加上 datagridview1.EndEdit

還是一樣存不進去

最有價值解答

o小高o
可以參考這種寫法
或許有幫助

BindingSource.DataSource = DataTable
DataGridView.DataSource = BindingSource

DataGridView_CellLeave(sender, e) {
   DataGridView dgv = sender as DataGridView;
   BindingSource bs = dgv.DataSource as BindingSource;
   if (bs != null) {
     bs.EndEdit();
     DataTable dt = bs.DataSource as DataTable;
     if(dt != null)
     {
       this.Events.TestTableAdapter.Update(dt);
     }
   }
}

o小高o
或者試試這樣
DataGridView1.DataSource = dt
DataGridView1.DataBind() //加上這行
danny
好的,謝謝,我再試試
danny
謝謝,改成 BindingSource1.EndEdit() 後,是可以存進去了


不過我還是想了解,下列的做法,要怎麼正確的存檔進去 ?
Dim xname As String = InputBox("請輸入姓名", "更改姓名")
DataGridView1.CurrentRow.Cells("姓名").Value = xname
da.Update(dt) '存檔

誰是誰
既然用程式碼更改,為何不是更改資料來源的 DataTable,而是更改畫面上的 DataGridView ?
danny
謝謝

因為 DataGridView1 的欄位可以排序,當使用者點欄位標題重新排列後,

DataGridView1.rows(5) 不一定等於 dt.rows(5)

要怎麼知道要改資料來源 dt 的那一列呢 ?

誰是誰
(1) 單靠 Datatable,你可以從畫面取得資料的索引鍵值,透過索引鍵值取得 Datatable 內的特定資料
(2) 或是 中間在加上一層 BindingSource,靠 BindingSource.Current 屬性就可以抓目前資料
P陳
為了解決這個問題我很早之前的寫法
A01捐款資料登錄.G_捐款明細.BeginEdit(False)
A01捐款資料登錄.G_捐款明細.EndEdit()

目前我不會直接用 datatable 來當資料來源,而是用 BaidingSource
而是用以下的寫法
bs1.bindingsource=tabledt
dgv1.datasource=bs1

bs1.endedit
dgv1.endedit
再作 Update 的動作
----------------------------
之前我一直以為差不多,最後才知差很多,建議您也一樣。
danny
好的,謝謝各位
回到頂部